Improve performances for TestFramework and Json
Improve performances for type comparisons especially in Test Framework and Json classes but for sure used in few other plances.
Details about Problem
nanoFramework area: ( Other tools )
VS version:
VS extension version:
Target:
Firmware image version:
Description
So far all type comparisons in Test Framework (eg here: ) and in Json (eg here: ) are using strings. They should use typeof instead.
Using typeof on the following simple sample shows a performance improvement by 2 times. The first loop, using string took 1000 ms to execute on an ESP32. The second loop using typeof only uses 510 ms.
Memory wise, typeof will return a singleton on the system types, so there is no additional footprint neither other performance penalty.
We should consider moving from string comparisons to typeof.
using System;
using System.Diagnostics;
using System.Threading;
Debug.WriteLine("Hello from nanoFramework!");
object[] array = new object[5];
array[0] = (int)42;
array[1] = (byte)42;
array[2] = "This is a super string";
array[3] = (ulong)42;
array[4] = new Version(4, 2);
Stopwatch sw = Stopwatch.StartNew();
for (int loop = 0; loop < 100; loop++)
{
for (int i = 0; i < array.Length; i++)
{
object obja = array.GetValue(i);
var typea = obja.GetType();
CompareUsingString(typea);
}
}
sw.Stop();
Console.WriteLine("------------------");
Console.WriteLine($"Total time: {sw.ElapsedMilliseconds}");
sw = Stopwatch.StartNew();
for (int loop = 0; loop < 100; loop++)
{
for (int i = 0; i < array.Length; i++)
{
object obja = array.GetValue(i);
var typea = obja.GetType();
CompareUsingTypeof(typea);
}
}
sw.Stop();
Console.WriteLine("------------------");
Console.WriteLine($"Total time: {sw.ElapsedMilliseconds}");
void CompareUsingString(Type typea)
{
switch (typea.FullName)
{
case "System.Int32":
Console.WriteLine("System.Int32");
break;
case "System.UInt32":
Console.WriteLine("System.UInt32");
break;
case "System.Byte":
Console.WriteLine("System.Byte");
break;
case "System.SByte":
Console.WriteLine("System.SByte");
break;
case "System.Int16":
Console.WriteLine("System.Int16");
break;
case "System.UInt16":
Console.WriteLine("System.UInt16");
break;
case "System.Int64":
Console.WriteLine("System.Int64");
break;
case "System.UInt64":
Console.WriteLine("System.UInt64");
break;
case "System.Char":
Console.WriteLine("System.Char");
break;
case "System.Double":
Console.WriteLine("System.Double");
break;
case "System.Boolean":
Console.WriteLine("System.Boolean");
break;
case "System.Single":
Console.WriteLine("System.Single");
break;
default:
Console.WriteLine("Non system type");
break;
}
}
void CompareUsingTypeof(Type typea)
{
if (typea == typeof(int))
{
Console.WriteLine("System.Int32");
}
else if (typea == typeof(uint))
{
Console.WriteLine("System.UInt32");
}
else if (typea == typeof(byte))
{
Console.WriteLine("System.Byte");
}
else if (typea == typeof(sbyte))
{
Console.WriteLine("System.SByte");
}
else if (typea == typeof(short))
{
Console.WriteLine("System.Int16");
}
else if (typea == typeof(ushort))
{
Console.WriteLine("System.UInt16");
}
else if (typea == typeof(long))
{
Console.WriteLine("System.Int64");
}
else if (typea == typeof(ulong))
{
Console.WriteLine("System.UInt64");
}
else if (typea == typeof(char))
{
Console.WriteLine("System.Char");
}
else if (typea == typeof(double))
{
Console.WriteLine("System.Double");
}
else if (typea == typeof(bool))
{
Console.WriteLine("System.Boolean");
}
else if (typea == typeof(float))
{
Console.WriteLine("System.Single");
}
else
{
Console.WriteLine("Non system type");
}
}
Thread.Sleep(Timeout.Infinite);
@Ellerbach
Hope you haven't start working on it.
I've played a little bit with benchmark tool, just to see how it's working in real example. So I've checked every unit test in Json lib and created benchmarks based on them. I've tried to avoide duplications in benchmarks, so not every unit test was moved. Here are results:

Few more left to do:
- Benchmark lib as nuget 😅
- Extend ReferenceTypesSerializationBenchmark class
- Increase sample count in one iteration (there is a lot of results in range of 0 to 20 ms)
After that we should get a solid baseline for further improvements.
Also, I've found few minor bugs in deserialization 😅
So great! Just can't wait :-D
@Ellerbach Let me do it :) I'm already working on refactoring JSON lib, I've extracted all type compare to single method, so should be easy to change. Also I'll take care of test framework.
@josesimoes Reopening, still need JSON part.