Mr-Markus / ZigbeeNet

A .NET Standard library for working with ZigBee
Eclipse Public License 1.0
130 stars 46 forks source link

ZclDataType refactor #144

Closed oblaise closed 3 years ago

oblaise commented 3 years ago

In ZclDataType, the use of Linq and Single results in enumerating the complete Dictionary each time the Get(DataType type) function is called. This has a serious performance impact as this function is called a lot from cluster classes (see first line of benchmark below).

First step was thus to refactor the function to effectively use the Dictionary (around 150x improvement).

Then I had the intuition that a Dictionary wasn't the most efficient way to implement that function. So I made some performance and memory benchmarks to check 3 alternatives to Dictionary: a class derived from KeyedCollection, an Array[16][16] that contains only no empty rows and a simple Array[256], the first giving a small memory advantage.

After analysis it appears that using a simple Array[256] is really giving a performance advantage and that the memory cost of that approach is lower than the Dictionary, even if this can be counter-intuitive at first glance. So I changed the class to use the simple array approach.

I also changed the ZigBeeProfileType to a pure Enum approach which is sufficient for that class.

Benchmark results

In the tables below : Get -> original Get function, Dict -> using the Dictionary, KeyedValue -> using a KeyedCollection, *SquareArray -> using Array[16][16], Array -> using Array[256]


BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i5-5200U CPU 2.20GHz (Broadwell), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.1.407
  [Host]     : .NET Core 3.1.13 (CoreCLR 4.700.21.11102, CoreFX 4.700.21.11602), X64 RyuJIT
  DefaultJob : .NET Core 3.1.13 (CoreCLR 4.700.21.11102, CoreFX 4.700.21.11602), X64 RyuJIT
Method Mean Error StdDev
Get 1,464.0581 ns 14.1086 ns 11.7813 ns
GetDict 10.2695 ns 0.1114 ns 0.0870 ns
GetKeyedValue 18.2015 ns 0.4702 ns 0.5775 ns
GetSquareArray 2.7174 ns 0.1224 ns 0.1085 ns
GetArray 0.4355 ns 0.0930 ns 0.0870 ns
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
CreateDict 1,979.5 ns 38.69 ns 66.74 ns 1.9875 - - 3.05 KB
CreateKeyedValue 6,579.2 ns 70.85 ns 59.16 ns 7.9041 - - 12.13 KB
CreateArray 549.6 ns 10.62 ns 9.93 ns 1.3351 - - 2.05 KB
CreateSquareArray 1,157.4 ns 22.45 ns 25.86 ns 1.1768 - - 1.8 KB
Mr-Markus commented 3 years ago

Awesome! Thanks for it. Really Interessting benchmark values. I would release a new version today.