1
0
mirror of synced 2025-12-19 18:06:02 -05:00
Files
core/release-notes/10.0/preview/preview3/runtime.md
James Montemagno d136e6ab76 .NET 10 - Preview 3 (#9817)
* stage P3

* cleanup

* efcore doc updates for preview 3

* .NET MAUI in .NET 10 Preview 3 (#9826)

* .NET MAUI in .NET 10 Preview 3

* Update .NET MAUI release notes for preview 3

* .NET 10 P3 - SDK Notes (#9822)

* SDK Start

* Add first draft of SDK features for p3

* Update release-notes/10.0/preview/preview3/sdk.md

* Update release-notes/10.0/preview/preview3/sdk.md

* Update release-notes/10.0/preview/preview3/sdk.md

Co-authored-by: Youssef Victor <youssefvictor00@gmail.com>

* Update release-notes/10.0/preview/preview3/sdk.md

Co-authored-by: Youssef Victor <youssefvictor00@gmail.com>

---------

Co-authored-by: Chet Husk <chusk3@gmail.com>
Co-authored-by: Chet Husk <baronfel@users.noreply.github.com>
Co-authored-by: Youssef Victor <youssefvictor00@gmail.com>

* .NET 10 Preview 3 - Runtime (#9823)

* .NET 10 P3 Runtime

* Add JIT notes

* Fix indentation

* Feedback

---------

Co-authored-by: Aman Khalid (from Dev Box) <amankhalid@microsoft.com>

* Add ASP.NET Core release notes for .NET 10 Preview 3 (#9835)

* Add ASP.NET Core release notes for .NET 10 Preview 3

* Add server-sent events

* Add declarative state persistence

* Add OpenAPI template option

* Add min API validation

* Add built-time env for Blazor WebAssembly

* Apply edits

* Apply suggestions from PR review

Co-authored-by: Wade Pickett <wpickett@microsoft.com>

* Update release-notes/10.0/preview/preview3/aspnetcore.md

Co-authored-by: Wade Pickett <wpickett@microsoft.com>

* Update release-notes/10.0/preview/preview3/aspnetcore.md

Co-authored-by: Wade Pickett <wpickett@microsoft.com>

* Update release-notes/10.0/preview/preview3/aspnetcore.md

Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>

* Update release-notes/10.0/preview/preview3/aspnetcore.md

Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>

* Update release-notes/10.0/preview/preview3/aspnetcore.md

* Update release-notes/10.0/preview/preview3/aspnetcore.md

Co-authored-by: Daniel Roth <daroth@microsoft.com>

---------

Co-authored-by: Mike Kistler <mikekistler@microsoft.com>
Co-authored-by: Wade Pickett <wpickett@microsoft.com>
Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Co-authored-by: Pavel Savara <pavelsavara@microsoft.com>

* Updates for P3 (#9831)

* .NET 10 P3 - Libraries (#9824)

* .NET 10 P3 - Libraries

* Introduce an AOT-Safe Constructor for ValidationContext

* Support for Telemetry Schema URLs in ActivitySource and Meter

* Byte-Level Support in BPE Tokenizer

* ML.NET notes

* Tensor update notes

---------

Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Michael Sharp <51342856+michaelgsharp@users.noreply.github.com>

* cleanup

* cleanup

* cleanup

* cleanup

* Initial draft of P3 release notes (#9832)

* cleanup

* cleanup

* Update release-notes/10.0/preview/preview3/csharp.md

Co-authored-by: Martin Costello <martin@martincostello.com>

* Update release-notes/10.0/preview/preview3/aspnetcore.md

Co-authored-by: Mike Kistler <mikekistler@microsoft.com>

* update code block

* Add global.json local sdk support details

* Added WPF notes (#9844)

* update readmes

* fix readme

* Updated 10.0.0-preview.3.md with content and Nuget list

* cleanup 1

* Implement feature X to enhance user experience and optimize performance

* Update release-notes/10.0/preview/preview3/10.0.0-preview.3.md

Co-authored-by: Martin Costello <martin@martincostello.com>

* Updated windowsdesktop Urls

* cleanup

* updat elinux

* udpated

* Fix table

---------

Co-authored-by: maumar <maumar@microsoft.com>
Co-authored-by: David Ortinau <david.ortinau@microsoft.com>
Co-authored-by: Chet Husk <chusk3@gmail.com>
Co-authored-by: Chet Husk <baronfel@users.noreply.github.com>
Co-authored-by: Youssef Victor <youssefvictor00@gmail.com>
Co-authored-by: Aman Khalid (from Dev Box) <amankhalid@microsoft.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: Mike Kistler <mikekistler@microsoft.com>
Co-authored-by: Wade Pickett <wpickett@microsoft.com>
Co-authored-by: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Co-authored-by: Pavel Savara <pavelsavara@microsoft.com>
Co-authored-by: Merrie McGaw <mmcgaw@microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Michael Sharp <51342856+michaelgsharp@users.noreply.github.com>
Co-authored-by: Kathleen Dollard <kdollard@microsoft.com>
Co-authored-by: Martin Costello <martin@martincostello.com>
Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com>
Co-authored-by: victorisr <victorisr@microsoft.com>
2025-04-10 13:03:15 -07:00

6.1 KiB

.NET Runtime in .NET 10 Preview 3 - Release Notes

Here's a summary of what's new in the .NET Runtime in this preview release:

.NET Runtime updates in .NET 10:

Stack Allocation of Small Arrays of Reference Types

Since .NET 9's release, we have introduced new enhancements to the JIT compiler's ability to stack-allocate objects that don't outlive their creation contexts. Preview 1 expanded the JIT's stack allocation optimization to small, fixed-sized arrays of value types. This means small arrays of types not tracked by the garbage collector (GC) are allocated on the stack instead of the heap when it is safe to do so, reducing GC pressure and unlocking additional optimizations like scalar promotion. However, this optimization would not kick in for examples like the below:

static void Print()
{
    string[] words = {"Hello", "World!"};
    foreach (var str in words)
    {
        Console.WriteLine(str);
    }
}

The lifetime of words is scoped to the Print method, and the JIT can already stack-allocate the strings "Hello" and "world!". However, the fact that words is an array of strings, a reference type, would previously stop the JIT from stack-allocating it. Now, the JIT can eliminate every heap allocation in the above example. At the assembly level, the code for Print used to look like this:

Program:Print() (FullOpts):
       push     rbp
       push     r15
       push     rbx
       lea      rbp, [rsp+0x10]
       mov      rdi, 0x7624BAEF8360      ; System.String[]
       mov      esi, 2
       call     CORINFO_HELP_NEWARR_1_OBJ
       mov      rdi, 0x762534A02D10      ; 'Hello'
       mov      gword ptr [rax+0x10], rdi
       mov      rdi, 0x762534A02D30      ; 'World!'
       mov      gword ptr [rax+0x18], rdi
       lea      rbx, bword ptr [rax+0x10]
       mov      r15d, 2
G_M2084_IG03:  ;; offset=0x0043
       mov      rdi, gword ptr [rbx]
       call     [System.Console:WriteLine(System.String)]
       add      rbx, 8
       dec      r15d
       jne      SHORT G_M2084_IG03
       pop      rbx
       pop      r15
       pop      rbp
       ret

Notice how we call CORINFO_HELP_NEWARR_1_OBJ to allocate words on the heap. Now, the assembly looks like this:

Program:Print() (FullOpts):
       push     rbp
       push     r15
       push     rbx
       sub      rsp, 32
       lea      rbp, [rsp+0x30]
       vxorps   xmm8, xmm8, xmm8
       vmovdqu  ymmword ptr [rbp-0x30], ymm8
       mov      rdi, 0x700BFC98B0C0      ; System.String[]
       mov      qword ptr [rbp-0x30], rdi
       lea      rdi, [rbp-0x30]
       mov      dword ptr [rdi+0x08], 2
       lea      rbx, [rbp-0x30]
       mov      rdi, 0x700C76402D10      ; 'Hello'
       mov      gword ptr [rbx+0x10], rdi
       mov      rdi, 0x700C76402D30      ; 'World!'
       mov      gword ptr [rbx+0x18], rdi
       add      rbx, 16
       mov      r15d, 2
G_M2084_IG03:  ;; offset=0x005A
       mov      rdi, gword ptr [rbx]
       call     [System.Console:WriteLine(System.String)]
       add      rbx, 8
       dec      r15d
       jne      SHORT G_M2084_IG03
       add      rsp, 32
       pop      rbx
       pop      r15
       pop      rbp
       ret

For more information on stack allocation improvements in the JIT compiler, check out dotnet/runtime #108913.

Improved Code Layout

The JIT compiler organizes your method's code into basic blocks that can only be entered at the first instruction, and exited via the last instruction. As long as the JIT appends a jump instruction to the end of each block, the program can be laid out in any block order without changing runtime behavior. However, some layouts produce better runtime performance than others:

  • Placing a block before its successor in memory means the JIT does not need to emit a jump instruction to it, reducing code size and the potential for CPU pipelining penalties.
  • Placing frequently-executed blocks near each other increases their likelihood of sharing an instruction cache line, reducing instruction cache misses.

Thus, the JIT has an optimization where it tries to find a block ordering that exhibits the above traits. Previously, the JIT would compute a reverse postorder (RPO) traversal of the program's flowgraph as an initial layout, and then make iterative transformations to it. RPO tends to produce layouts with little branching by placing each block before its successors, unless the block is in a loop. If profile data suggests a block is rarely executed, the JIT then moves it to the end of the method to compact the hotter parts of the method. Finally, the JIT tries to eliminate hot branches by moving the successor of the branch up to its predecessor.

The challenge of finding a performant block layout stems from the fact that the above goals are frequently orthogonal to each other. For example, in the process of eliminating a hot branch, the JIT might move other hot blocks further away from their successors, reducing hot code density overall. Because each transformation is local in scope, it's difficult to model how one transformation's changes affect another's. To solve this, the JIT now models the block reordering problem as a reduction of the asymmetric Travelling Salesman Problem, and implements the 3-opt heuristic for finding a near-optimal traversal. The "distance" between each block is modeled by the execution count of the preceding block, multiplied by the likelihood that the block branches to its successor. The JIT then searches for a layout with the shortest distance from the method entry to the method exit, frequently yielding a layout with dense hot paths, and relatively short branches.

To learn more about improvements to code layout in .NET 10, check out dotnet/runtime #107749.