question

vbAtom avatar image
0 Votes"
vbAtom asked vbAtom edited

How to prebuild C# generics before runtime

Hi,

Currently, C# generics are built at runtime. First time, generics execution is very slow because runtime compilation.

How to avoid runtime compilation...how to get target x64 or x86 binaries where generics are already compiled to native binary.

Is there LINK option for that I am missing?

Thanks in advance!
Vladimir

dotnet-csharpvs-generaldotnet-runtimevs-msbuilddotnet-cli
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

APoblacion avatar image
1 Vote"
APoblacion answered APoblacion edited

If I understand correctly, you want to bypass the JIT-compiler (Just In Time). For classical .Net Framework, you have a tool called NGEN.EXE (Native Image GENerator), which can take your IL files and turn them into executable binaries. Note that this is unrelated to whether you use Generics or not; the JIT and NGEN apply to any code with or without Generics.

Link to documentation.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

vbAtom avatar image
0 Votes"
vbAtom answered vbAtom edited

So, you want to say there is no LINK/BUILD option in Visual Studio that can build native image?

Only NGEN.exe that you must call from script or manually from cmd?

· 29
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Indeed, the build/link option generates what appears to be an .exe file, but it only contains a tiny bit of executable code that loads the .Net runtime, and the rest is just Intermediate Language (IL) which needs to be JIT-compiled before it can be executed. To convert the IL into a native binary, you need to post-process the file with NGEN. Note that this refers to the "classical" .Net Framework; for .Net Core there is a separate set of tools.

1 Vote 1 ·

First, thank you very much for answer!

Hm, NGEN is almost no use...did you see MSDN topic about it?

It is strange, and probably there is some good reason why C# does not have a prori generation of best optimal code and does not generate best (fastest) code.
This is big drawback.

For example, experimentally, one line of generic code first time took 20 milisec to execute...and when you compare with 1 ms to CopyMemory for 8 Mb memory...it is unforgivable.
For time demanding applications, like "realtime" applications, DirectShow filters, DirectX ... when 60 FPS = 16 ms is time you want to generate drawing commands and present new screen to user...and while you are doing it...it must first compile it?

0 Votes 0 ·

If you force the construction of generic types on initialization stage (executing something like new List<MyStructure> or new MyGenericClass<MyStructure>), when the performance is not so important, then it should use the already created code later at run-time.

Probably C# is not always fully suitable for real-time applications. You can make some parts in other languages, such as C++ or Assembler.

1 Vote 1 ·
Show more comments

It would be nice, logical, when you first start application, that system first compile it to best binary, and then start execution. Second start, get this binary from cache without compilation. Why to have separate tool like NGEN?

Also, I have not find any attribute or #pragma like declaration to explicitly say ... "these lines of code/function must fly...compile it best you can for speed".

C# is here for very long time...it must be a good reason why this is not implemented jet.

0 Votes 0 ·

Well, it does... more or less. When you start the IL exe, for each method that is executed the method is JIT-Compiled and cached in memory. This is fast because only the methods that you actually invoke need to be compiled. If a method is invoked again, it does not need to be recompiled, since the executable is already cached in memory.
However, there is currently no option to save to disk these pieces that have already been compiled. Would it be worth doing? I'm not sure. The JIT compiler is so fast that there is a possibility that loading the compiled code from disk might be slower that JIT-compiling the IL. Someone must have analyzed it before deciding that the "good" options were the ones that we have, i.e., either precompile everything with NGEN or JIT-compile in memory the pieces that are being used.

1 Vote 1 ·
Show more comments

Still, I don't understand generics cannot be set to natural form when you build application...

if you, for example, have class SomeGenClass<T>

and you specify explicitly in the code.... SomeGenClass<byte> ... it should be set, like in C++ template after build, in complied form where all elements "T" are replaced for "byte".

0 Votes 0 ·

According to documentation, if T is a value type (e.g. byte or a structure), then the system will generate a new specialized version of the generic type, where T is substituted. (Different code for each T).

If T is a reference type (class), then the system generates a single specialized version, which is shared by all reference types. (A single code for all T).

2 Votes 2 ·
Show more comments

No, C# works differently. It does not replace the type in the template like C++. Instead, Generics have direct support in the libraries of the Framework. So the T is passed as a parameter and its type is used at runtime. This means that your code contains a single compiled instance of SomeGenClass<T>, regardless of how many different T's as used within your program.

1 Vote 1 ·
Show more comments