diff --git a/Asn1Parser/Asn1Reader.cs b/Asn1Parser/Asn1Reader.cs index 51207af..aa408ed 100644 --- a/Asn1Parser/Asn1Reader.cs +++ b/Asn1Parser/Asn1Reader.cs @@ -22,15 +22,17 @@ namespace SysadminsLV.Asn1Parser; /// public class Asn1Reader { // a list of primitive tags. Source: http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules#DER_encoding - static readonly List _excludedTags = [ 0, 1, 2, 5, 6, 9, 10, 13 ]; + // although we actively do lookups, it is NOT recommended to use sets (HashSet), because at current collection size + // lookups in HashSet are around 3-4x times slower than in plain list. + static readonly List _excludedTags = [ 0, 1, 2, 5, 6, 9, 10, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 ]; + static readonly List _multiNestedTypes = [ + (Byte)Asn1Type.SEQUENCE, + (Byte)Asn1Type.SEQUENCE | (Byte)Asn1Class.CONSTRUCTED, + (Byte)Asn1Type.SET, + (Byte)Asn1Type.SET | (Byte)Asn1Class.CONSTRUCTED + ]; readonly List _rawData = []; readonly Dictionary _offsetMap = []; - readonly List _multiNestedTypes = [ - (Byte)Asn1Type.SEQUENCE, - (Byte)Asn1Type.SEQUENCE | (Byte)Asn1Class.CONSTRUCTED, - (Byte)Asn1Type.SET, - (Byte)Asn1Type.SET | (Byte)Asn1Class.CONSTRUCTED - ]; AsnInternalMap currentPosition; Int32 childCount; diff --git a/tests/Asn1Parser.Tests/CollectionPerfTests.cs b/tests/Asn1Parser.Tests/CollectionPerfTests.cs new file mode 100644 index 0000000..d07de4b --- /dev/null +++ b/tests/Asn1Parser.Tests/CollectionPerfTests.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Asn1Parser.Tests; +[TestClass] +public class CollectionPerfTests { + static readonly List _list = [0, 1, 2, 5, 6, 9, 10, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]; + static readonly HashSet _hashSet = [0, 1, 2, 5, 6, 9, 10, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]; + const Int32 ITERATIONS = 1000000; + + [TestMethod] + public void TestFirstMatch() { + assertGlobal(0); + } + [TestMethod] + public void TestMiddleMatch() { + assertGlobal(20); + } + [TestMethod] + public void TestLastMatch() { + assertGlobal(30); + } + [TestMethod] + public void TestNoMatch() { + assertGlobal(255); + } + + static void assertGlobal(Byte searchByte) { + TimeSpan list = executeAction(_list.Contains, searchByte, ITERATIONS); + TimeSpan hashSet = executeAction(_hashSet.Contains, searchByte, ITERATIONS); + assertListIsFaster(list, hashSet); + } + static void assertListIsFaster(TimeSpan list, TimeSpan hashSet) { + Assert.IsTrue(list < hashSet); + } + //static void assertListIsFaster3xTimes(TimeSpan list, TimeSpan hashSet) { + // Double ratio = hashSet / list; + // Console.WriteLine(ratio); + // Assert.IsTrue(ratio >= 3); + //} + static TimeSpan executeAction(Func action, Byte searchValue, Int32 iterations) { + var sw = new Stopwatch(); + sw.Start(); + for (Int32 i = 0; i < iterations; i++) { + action.Invoke(searchValue); + } + sw.Stop(); + + return sw.Elapsed; + } +}