It would be useful to specify something like "Hello World".Length
in some special syntax that gets evaluated at compile time and replaced with 11 (becoming a constant) in the compiled binaries.
You mean it's not already converted to constant?
JIT compiler might optimize it but I want the language compiler to do it. In the generated IL code the string is constant but the value of its length is not.
I gave string as example. I want to be able to use more expressions to evaluated at compile time. Something like eval(simple expression)
.
What is the reason? Is it about performance? Or something else?
This is also related to #10972 and #9627 (there are similar examples in the latter issue).
The reason is simple. If we know that the value of an expression at run time is exactly same as at compile time, there is no point in deferring evaluation to run time.
@nvmkpk : I do quite like the idea, I do however see the following problem:
Imagine, that one is writing a (memory) profiler. The profiler would not register the function call int System::String::get_Length()
, as the function would be "precompiled" into its result. Thus the application profiling result could be incorrect compared to expected data/values.
My second question/concern: To which degree do you want this "optimization"? Should it apply to each completely deterministic function(-chain) with only constant input?
e.g. should the expression "Hello,World!".ToUpper().Remove(0,1)
be precompiled into "ELLO,WORLD!"
? Where do we draw the line?
_EDIT_: or should one use a pseudo-attribute like [compile]
, which one could put in front of fields/expressions?
@Unknown6656 That already happens, in the JIT compiled machine code, there is no call to get_Length()
, since it's inlined.
And you can't put attributes on expressions, at least not without #6671.
@svick : Interesting, I did not know the fact about get_Length()
-inlining.
Concerning the usage of attributes on expressions: During the composition of my previous comment I assumed, that issue #6671 will be implemented in the future C# version, as it has been marked as
[2 - Ready]
My second question/concern: To which degree do you want this "optimization"?
Hopefully in Release build, all of the optimizations.
Where do we draw the line?
Where-ever compiler can statically determine static or read-only or const-ness and exploit it :dancers:
That is fine for optimization part but I would like the developer to also call for compile time evaluation by using something like eval(expression)
. This would be better way than using attributes.
@choikwa (, @nvmkpk ): So, would the following expression be optimized (assuming, that a array<string>
shall be interpreted as constant, and that all functions do not use non-constant internal parameters and are fully deterministic)?
char a = (new string[] { "test", "string" })[1].Reverse().ToArray()[3]) - 'B';
// a now stores the character `0`
My point is: I _really_ do _love_ your proposal, but does too much optimization not take too much time on a big scale? Are arrays defined at compile time also a constant, if they remain unchanged?
_Imagine the calculation time for large for
-loops, nested conditions etc. which will be precompiled. Does not take this too much compilation time?_
_If anyone is interested, how the character is calculated in the example above:_
string[] arr = new string[] { "test", "string" };
char[] elem = arr[1].Reverse().ToArray(); // [g,n,i,r,s,t]
char r = elem[3]; // 'r' (0x72)
char a = r - 'B'; // 0x72 - 0x42 == 0x30 = '0'
// a now stores the character `0`
would the following expression be optimized?
A compiler worth its salt would optimize. I am hoping CoreCLR is to be such one. Maybe you can help make that happen :smile:
does too much optimization not take too much time on a big scale?
C++ already does this with constexpr and template meta. A saving grace is that you only do this once during compilation. In C# context, maybe this makes more sense in AOT compilation or more expensive ReJIT (don't we all want tiered JIT?).
PS. a lot of compilers already neuter optimization if method size is too large, to the detriment of performance just because compilation time would be excessive. Would not surprise me if CoreCLR had to do something similar since it's a VM.
@choikwa I think that you have me convinced on that point! :smile:
I knew that C++ has precompiled templates instead of runtime-generated generics, but I did not yet know about constexpr
. I think, that this is an excellent definition of constant expressions/methods (which needs some adaptation for C#)
Maybe you can help make that happen
I will try as much as I can :wink:
FYI this very issue is open in https://github.com/dotnet/coreclr/issues/3633
That is for optimzation. This proposal is about letting developer write general compile time expressions not just for string length.
Sorry for hijacking the issue. You are correct, and I agree that this should have some dependence on success of https://github.com/dotnet/roslyn/issues/6671
On the syntax -- I suggested const(...)
in #11259 which has a benefit of already being a keyword.
@nvmkpk May you move this to csharplang repo?
Issue moved to dotnet/csharplang #1028 via ZenHub
Most helpful comment
Hopefully in Release build, all of the optimizations.
Where-ever compiler can statically determine static or read-only or const-ness and exploit it :dancers: