La velocità di un’applicazione non dipende solo dagli algoritmi scelti dallo sviluppatore. Una parte sempre più importante del lavoro passa dal runtime (componente che esegue il codice e gestisce compilazione JIT, memoria e servizi di base): decide come tradurre il codice in istruzioni macchina, quali funzioni incorporare direttamente nel codice chiamante, come ridurre le allocazioni temporanee e come sfruttare al meglio registri e risorse della CPU.
.NET 11 rappresenta un passo avanti soprattutto per questo motivo: il runtime riesce a capire meglio ciò che l’applicazione sta facendo e, di conseguenza, elimina una quantità crescente di lavoro inutile. In diversi casi non serve modificare il sorgente: basta eseguire la stessa applicazione sul nuovo runtime per ottenere codice macchina migliore, meno allocazioni e percorsi di esecuzione più brevi.
È probabilmente questo l’aspetto più interessante della nuova versione, attesa in versione definitiva dal 10 novembre 2026 e già disponibile come Go Live (quindi adatta anche per l’impiego in produzione) sotto forma di release RC1.
Perché .NET 11 rappresenta un passo avanti
Microsoft racconta i miglioramenti di performance ottenuti e ottenibili con .NET 11: fare in modo che il runtime comprenda sempre meglio il codice e riesca ad eliminare operazioni che lo sviluppatore non dovrebbe essere costretto a ottimizzare manualmente è il balzo in avanti più importante.
Un esempio importante riguarda il JIT compiler: .NET utilizza già la Profile-Guided Optimization per osservare quali tipi e quali percorsi vengono utilizzati più frequentemente durante l’esecuzione. .NET 11 usa queste informazioni per capire più spesso quale metodo sarà eseguito: in questo modo JIT può evitare alcuni passaggi intermedi e, quando possibile, incorporare direttamente il codice del metodo chiamato in quello che lo richiama, riducendo il costo della chiamata.
Il risultato può essere sorprendente. Microsoft mostra casi nei quali un metodo che con .NET 10 richiedeva circa 7 nanosecondi e produceva un’allocazione da 24 byte scende sotto i 2 nanosecondi eliminando completamente l’allocazione.
La parte davvero interessante è il meccanismo: JIT riesce a capire quale metodo verrà probabilmente eseguito, lo incorpora nel codice chiamante e scopre che alcuni oggetti temporanei non servono più.
Dove .NET 11 prova davvero a fare la differenza
Le ottimizzazioni di .NET 11 toccano molti componenti, ma il filo conduttore è abbastanza semplice: ridurre il lavoro inutile. JIT riconosce meglio i percorsi di esecuzione più probabili, elimina più facilmente oggetti temporanei, riduce alcuni accessi alla memoria e produce in diversi casi codice macchina più compatto.
Un esempio riguarda la gestione degli oggetti che vivono pochissimo. Grazie a un’escape analysis più efficace, il runtime può capire quando un oggetto serve soltanto all’interno di un metodo ed evitare di allocarlo nello heap. Meno allocazioni significa anche meno pressione sul garbage collector, soprattutto nelle applicazioni che eseguono milioni di operazioni al secondo.
Un’altra novità interessante è Runtime Async. Oggi gran parte della logica necessaria a gestire async/await è generata dal compilatore C# sotto forma di macchine a stati.
.NET 11 sperimenta invece lo spostamento di parte di questo lavoro nel runtime, con l’obiettivo di ridurre il codice generato e lasciare più margine di ottimizzazione a JIT.
Ci sono poi miglioramenti molto concreti per chi sviluppa backend e API. System.Text.Json accelera varie operazioni di scansione e escaping delle stringhe; lo stack HTTP riduce alcune allocazioni; Socket.ConnectAsync introduce una modalità che può provare IPv4 e IPv6 in parallelo, utile quando una delle due connettività risponde lentamente o non funziona correttamente.
Cosa significa per chi sviluppa
La parte più interessante di .NET 11 è che molti dei benefici introdotti non richiedono nuove API né riscritture del codice. Applicazioni che fanno largo uso di JSON, HTTP, collezioni e operazioni asincrone possono ottenere vantaggi semplicemente passando al nuovo runtime.
Naturalmente non tutte le applicazioni miglioreranno allo stesso modo. Se il collo di bottiglia è una query lenta o un servizio remoto, un JIT più efficiente non farà miracoli.
Ma nei workload che spendono molto tempo dentro il runtime, ridurre allocazioni, copie e controlli ripetuti può tradursi in un aumento concreto del throughput e in una minore pressione sulla memoria.
C’è anche un’altra conseguenza pratica: alcune ottimizzazioni manuali scritte anni fa con Unsafe, puntatori o workaround per evitare controlli sui limiti potrebbero non essere più necessarie. Il JIT moderno riesce ormai a eliminare da solo molti di quei costi.
Il codice C# ha sempre meno bisogno di trucchi per risultare efficiente: il runtime “capisce meglio” ciò che il programma sta facendo e prova a trasformarlo in codice macchina più diretto, con meno allocazioni e meno passaggi superflui.
Per verificare il beneficio reale resta comunque una sola strada sensata: misurare. Confrontare la stessa applicazione su .NET 10 e .NET 11, usando workload realistici.