You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This example code does nothing with the parametric type value except to read and return as a result.
Therefore, it was surprising to find a strong difference in the code size and performance for value and reference types.
Is this expected?
The generic type is used for InlineArrayAsSpan calls generated under-the-hood by Roslyn. The JIT does not manage to remove all those runtime lookups as some of them feed control flow (in the end, there is no difference in taking the true and false path for these tests, but the JIT's DCE is not able to reason that far).
We could clean this up if we taught the early liveness passes how to DCE other things than stores, since then we can do it before we expand the runtime lookups into control flow here.
For current 9.0 milestone I'd ask to add a warning in docs "Don't use InlineArray with reference types for performance reason". This will save someone a lot of time searching for the reasons why their code is slow.
In general we expect shared generic code to be slightly slower than unshared code. For example, you will also see a slowdown for List<string>.set_Item compared to List<int>.set_Item. We don't try to document this anywhere, so I'm not sure it's warranted to do it for this case either, especially considering that I expect we can improve on this (either by improving our DCE, or by implementing #105586).
In general we expect shared generic code to be slightly slower than unshared code. For example, you will also see a slowdown for List.set_Item compared to List.set_Item.
While I was researching this problem, I measured this example too and the differences there are scanty, there is an understanding of this and it is acceptable.
If we compare 1 and 3 lines (InlineArray code - value vs referense) - diff is 2.47!
I don't insist on documenting. But the problem is that there are intuitive expectations that the new InlineArray is designed for high-performance code, although it works worse than the usual language constructs.
Activity
jaredpar commentedon Aug 8, 2024
Moving to runtime as this is a question about the ASM code generation.
dotnet-policy-service commentedon Aug 8, 2024
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.
jakobbotsch commentedon Aug 8, 2024
The generic type is used for
InlineArrayAsSpancalls generated under-the-hood by Roslyn. The JIT does not manage to remove all those runtime lookups as some of them feed control flow (in the end, there is no difference in taking the true and false path for these tests, but the JIT's DCE is not able to reason that far).We could clean this up if we taught the early liveness passes how to DCE other things than stores, since then we can do it before we expand the runtime lookups into control flow here.
iSazonov commentedon Aug 9, 2024
For current 9.0 milestone I'd ask to add a warning in docs "Don't use InlineArray with reference types for performance reason". This will save someone a lot of time searching for the reasons why their code is slow.
jakobbotsch commentedon Aug 9, 2024
Can you share a benchmark that shows a perf problem warranting such a statement? Your code here always throws
NullReferenceException.iSazonov commentedon Aug 9, 2024
Yes, sharplab example is minimal asm demo.
I attached working benchmark project for you.
genericlist.zip
jakobbotsch commentedon Aug 9, 2024
I get the following results:
In general we expect shared generic code to be slightly slower than unshared code. For example, you will also see a slowdown for
List<string>.set_Itemcompared toList<int>.set_Item. We don't try to document this anywhere, so I'm not sure it's warranted to do it for this case either, especially considering that I expect we can improve on this (either by improving our DCE, or by implementing #105586).Thoughts @dotnet/jit-contrib @jkotas?
JIT: Teach middle-end liveness to DCE dead calls without sideeffects
iSazonov commentedon Aug 9, 2024
While I was researching this problem, I measured this example too and the differences there are scanty, there is an understanding of this and it is acceptable.
If we compare 1 and 3 lines (InlineArray code - value vs referense) - diff is 2.47!
I don't insist on documenting. But the problem is that there are intuitive expectations that the new InlineArray is designed for high-performance code, although it works worse than the usual language constructs.
JIT: Fix `gtNodeHasSideEffects` checking call arguments
jakobbotsch commentedon Aug 9, 2024
I think we can get a fix for this into .NET 9. #106183 and #106185 both fix the performance disparity here.