We are currently going though the process of converting our codebase from .Net Framework 4.8 to .Net Core 3.1.
Some of the code is very performance-sensitive. One example is some code that applies a Hamming window filter; I was somewhat dismayed to discover that the .Net Core 3.1-compiled code runs around 30% more slowly than the same code compiled for .Net Framework 4.8.
I created a multitargeted SDK-style project as follows:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworkS>net48;netcoreapp3.1</TargetFrameworkS>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
</Project>
The code for this project is as follows (the important code is inside the for (int iter = ...
loop):
using System;
using System.Diagnostics;
namespace FooBar
{
class Program
{
static void Main()
{
#if NET48
Console.WriteLine("NET48: Is 64 bits = " + Environment.Is64BitProcess);
#elif NETCOREAPP3_1
Console.WriteLine("NETCOREAPP3_1: Is 64 bits = " + Environment.Is64BitProcess);
#else
Invalid build, so refuse to compile.
#endif
double[] array = new double[100_000_000];
var sw = Stopwatch.StartNew();
for (int trial = 0; trial < 100; ++trial)
{
sum(array);
}
Console.WriteLine("Average ms for calls to sum() = " + sw.ElapsedMilliseconds/100);
Console.ReadLine();
}
static double sum(double[] array)
{
double s = 0;
for (int i = 0; i < array.Length; ++i)
{
s += array[i];
}
return s;
}
}
}
Timing a release x86 build for .Net Core 3.1 and .Net Framework 4.8 I get the following results:
.Net Core 3.1:
NETCOREAPP3_1: Is 64 bits = False
Average ms for calls to sum() = 122
.Net Framework 4.8:
NET48: Is 64 bits = False
Average ms for calls to sum() = 96
Thus the .Net Core 3.1 results are around 30% slower than .Net Framework 4.8.
NOTE: This only affects the x86 build. For an x64 build, the times are similar between .Net Framework and .Net Core.
I find this most disappointing, particularly since I thought that .Net Core would be likely to have better optimization ...
Can anyone suggest a way to speed up the .Net Core output so that it is in the same ballpark as .Net Framework 4.8?
[EDIT] I've updated the code and the .csproj to the latest version I'm using for testing. I added some code to indicate which target and platform is running, just to be certain the right version is being run.
With this edit, I am basically just timing how long it takes to sum all 100,000,000 elements of a large double[] array.
I can reproduce this on both my PCs and my laptop, which are running the latest Windows 10 and Visual Studio 2019 installations + latest .Net Core 3.1.
However, given that other people cannot reproduce this, I will take Lex Li's advice and post this on the Microsoft github page.
NET Core is faster for working with more modern libraries and programming languages. It is more lightweight and modular than . NET Framework, and you can use multiple versions of . NET in the same project.
Net Core 3.1-compiled code runs around 30% more slowly than the same code compiled for .
you can experience significant performance improvements if you run the latest version of the Microsoft . NET Framework (version 4.5 or higher). Gains of up to 25% faster execution are possible based on our testing, but individual results may vary depending on the hardware and software environments in use.
Thus the .Net Core 3.1 results are around 30% slower than .Net Framework 4.8. NOTE: This only affects the x86 build. For an x64 build, the times are similar between .Net Framework and .Net Core.
NETCOREAPP3_1: Is 64 bits = False Average ms for calls to sum () = 122 Thus the .Net Core 3.1 results are around 30% slower than .Net Framework 4.8. NOTE: This only affects the x86 build.
One example is some code that applies a Hamming window filter; I was somewhat dismayed to discover that the .Net Core 3.1-compiled code runs around 30% more slowly than the same code compiled for .Net Framework 4.8.
The pressure firstly came only from Microsoft but now also from the .NET community. You can feel that, especially when observing third party opensource projects. Slowly but steadily, they are slowing the development of full .NET Framework related code and are moving to the .NET Core framework.
Cannot reproduce.
Looks like .NET Core 3.1 is faster at least for x86. I checked it 5 or more times for each build and the Output is nearly the same.
.NET Framework 4.8
Is 64 bits = False
Computed 4199,58 in 00:00:01.2679838
Computed 4199,58 in 00:00:01.1270864
Computed 4199,58 in 00:00:01.1163893
Computed 4199,58 in 00:00:01.1271687
Is 64 bits = True
Computed 4199,58 in 00:00:01.0910610
Computed 4199,58 in 00:00:00.9695353
Computed 4199,58 in 00:00:00.9601170
Computed 4199,58 in 00:00:00.9696420
.NET Core 3.1
Is 64 bits = False
Computed 4199,580000000003 in 00:00:00.9852276
Computed 4199,580000000003 in 00:00:00.9493986
Computed 4199,580000000003 in 00:00:00.9562083
Computed 4199,580000000003 in 00:00:00.9467359
Is 64 bits = True
Computed 4199,580000000003 in 00:00:01.0199652
Computed 4199,580000000003 in 00:00:00.9763987
Computed 4199,580000000003 in 00:00:00.9612935
Computed 4199,580000000003 in 00:00:00.9815544
NET48: Is 64 bits = False
Average ms for calls to sum() = 110
NETCOREAPP3_1: Is 64 bits = False
Average ms for calls to sum() = 110
Intel(R) Core(TM) i7-4700HQ CPU @ 2.40GHz
Base speed: 2,40 GHz
Sockets: 1
Cores: 4
Logical processors: 8
Virtualization: Enabled
L1 cache: 256 KB
L2 cache: 1,0 MB
L3 cache: 6,0 MB
If the code is so performance-sensitive, maybe SIMD may help.
using System.Numerics;
const int ITERS = 100000;
int vectorSize = Vector<double>.Count;
Console.WriteLine($"Vector size = {vectorSize}");
for (int trial = 0; trial < 4; ++trial)
{
double windowSum = 0;
sw.Restart();
for (int iter = 0; iter < ITERS; ++iter)
{
Vector<double> accVector = Vector<double>.Zero;
for (int i = 0; i <= window.Length - vectorSize; i += vectorSize)
{
Vector<double> v = new Vector<double>(window, i);
accVector += Vector.Abs(v);
}
windowSum = Vector.Dot(accVector, Vector<double>.One);
}
Console.WriteLine($"Computed {windowSum} in {sw.Elapsed}");
}
Awesomeness of .NET Core is here :)
.NET Core 3.1
Is 64 bits = False
Vector size = 4
Computed 4199,58 in 00:00:00.3678926
Computed 4199,58 in 00:00:00.3046166
Computed 4199,58 in 00:00:00.2910941
Computed 4199,58 in 00:00:00.2900221
Is 64 bits = True
Vector size = 4
Computed 4199,58 in 00:00:00.3446433
Computed 4199,58 in 00:00:00.2616570
Computed 4199,58 in 00:00:00.2606452
Computed 4199,58 in 00:00:00.2582038
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With