Nyrest/FastGenericNew

First Run is slow

JeffBusterCase opened this issue · 12 comments

First Run is slow

Hi. thanks for the comment.

In most cases, we can only choose one of first-run speed and post-run speed on a managed platform.
However. using ILEmit instead of Expression can shorten the first run time a bit.
But this will need an overhaul of the entire library.

I'll try it tomorrow.

Maybe adding a Initialization? I don't know if this is possible.... Before a project is run.?

Maybe adding a Initialization? I don't know if this is possible.... Before a project is run.?

I think it can't be a solution.
You just moved that 1ms to elsewhere but it won't change the fact that it took 1ms.

This one displays the sad gap even more:
image

This one displays the sad gap even more: image

Can you provide the source code so I can reproduce this?

Here: JeffBusterCase/BenchmarkFastNewManually

Thanks. I see the code and I think there are some issues with the measuring.

First, you shouldn't benchmark them in parallel.
It's because two or more threads can be assigned to the same CPU core and they will be certainly slower than others.
You should benchmark them one by one instead.

And you should use Stopwatch instead of DateTime.

Stopwatch automatically checks for the existence of high-precision timers.
It is worth mentioning that DateTime.Now often is quite a bit slower than DateTime.UtcNow due to the work that has to be done with timezones, DST and such.
DateTime.UtcNow typically has a resolution of 15 ms. See John Chapman's blog post about DateTime.Now precision for a great summary.

https://stackoverflow.com/questions/28637/is-datetime-now-the-best-way-to-measure-a-functions-performance

It's recommended to use Benchmark.NET
https://benchmarkdotnet.org/articles/overview.html

I updated the code to better match the correct benchmark, but still... the initialization is what kills the objective :(
https://github.com/JeffBusterCase/BenchmarkFastNewManually
image

On the last 2 lines:
FastNew[NoInit] takes 8x times more time than Common (The two of them on 60k iterations)

This issue is delayed to 3.2.0 due I found a solution that better than ILGenerator.
#19

Solved in #19
you can enable FastGenericNew.SourceGenerator to call GetActivationInfo by adding this to the project file

<PropertyGroup>
    <FastNew_AllowUnsafeImplementation>true</FastNew_AllowUnsafeImplementation>
</PropertyGroup>

Sorry, I didn't understand.. Shouldn't this be a 'official' fix instead of a workaround/option.....
How can I test on my project witthout the Nuget Version (Still on 3.1.0-preview)

Sorry, I didn't understand.. Shouldn't this be a 'official' fix instead of a workaround/option..... How can I test on my project witthout the Nuget Version (Still on 3.1.0-preview)

This is an 'official' fix. the new implementation is stable now after working on it.
You can see how this library work now by checking the generated code: https://github.com/Nyerst/FastGenericNew/tree/main/FastGenericNew/_generated/FastGenericNew.SourceGenerator/FastGenericNew.SourceGenerator.Generator

The reason why this is an option is that it's slower than the classic FastNew
which defeats the purpose of this library

v3.2.0 is not released yet because there are still some minor jobs for the Unit Test project to do.
For now, you can try v3.2.0 by cloning this repo and compiling it.
Note that you will need .NET 7 SDK to compile this library.

You can reproduce the Benchmark by running the FastGenericNew.Benchmarks project.