Con l'introduzione di .NET Core, Microsoft ha messo in discussione l'intero .NET Framework che si è sviluppato negli anni e, grazie ad un nuovo processo di sviluppo, fatto da iterazioni più veloci, il coinvolgimento della community e il confrontarsi con altri prodotti, questo ha portato ad un'estrema ottimizzazione delle architetture e le prestazioni del runtime e delle librerie.
In questo processo si è visto come nel mondo .NET esistono tre modi diversi per allocare la memoria a seconda delle necessità: di stack, nell'heap non gestito, nell'heap gestito. Quest'ultimo è quello che usiamo più abitualmente ed è fatto di oggetti creati con la parola chiave new oppure di array. A seconda del tipo di allocazione, però, dobbiamo scorrere e modificare i byte in modi differenti.
Mediante l'introduzione di un nuovo pacchetto NuGet System.Memory attualmente in prerelease, invece, possiamo ora uniformare l'accesso e ottimizzare l'uso della memoria evitando inutili allocazioni. Installato il pacchetto vengono forniti due tipi ReadOnlySpan<T> e Span<T> rispettivamente per leggere o per leggere e modificare una sequenza. Disponiamo, inoltre, di extension method per agevolarci nelle conversioni, per esempio da una stringa.
// Crea uno span sulla base di una stringa // cioè di un array di char ReadOnlySpan<char> stringaSpan = "Questa è una stringa".AsSpan();
La funzione Slice, tra le più interessanti, restituisce un nuovo ReadOnlySpan<T>, una struct di basso impatto, che si riferisce sempre alla medesima area di memoria o ad un suo sottoinsieme, senza quindi creare nuovi array o nuove stringhe.
// Stampa 6 Console.WriteLine(stringaSpan.Length); // Stampa false Console.WriteLine(stringaSpan.IsEmpty); // Converto in un nuovo array string questaString = new string(questaSpan.ToArray()); Console.WriteLine(questaString);
Partendo da un array o da allocazioni non gestite, possiamo creare uno Span<T> e proseguire quindi a travasi o a manipolazioni.
char[] charArray = "Questa è una stringa".ToCharArray(); // Span dall'array, modifabile Span<char> stringa2Span = new Span<char>(charArray); // Errore a runtime, troppo piccolo "Quella non".AsSpan().CopyTo(stringa2Span.Slice(0, 6)); // Copio in uno spazio sufficiente "quella".AsSpan().CopyTo(stringa2Span.Slice(0, 6)); Span<byte> bytesSpan = stringa2Span.AsBytes(); // Cambio il primo carattere in "Q" maiuscolo. In unicode sono due byte bytesSpan[0] = 81; bytesSpan[1] = 0; // Converto in un array char[] charArray2 = stringa2Span.ToArray(); // Stampa false, viene ottenuta una nuova allocazione Console.WriteLine(Object.ReferenceEquals(charArray, charArray2)); // Stampa "Quella è una stringa" dall'array originale string questaString2 = new string(charArray); Console.WriteLine(questaString2);
Nell'esempio viene mostrato come sia anche possibile passare ad interpretazioni di tipo diverso, pur manipolando sempre la stessa area di memoria.
L'uso di questa struttura, quindi, è l'ideale quando dobbiamo analizzare o manipolare sequenze di aree di memoria. E' prevista anche l'introduzione di un Memory<T>, una sorta di factory per Span<T>, utile per interfacciarsi anche con Stream, ma al momento non risulta ancora disponibile. Per maggiori dettagli rimandiamo alla issue dedicata allo sviluppo.
https://github.com/dotnet/coreclr/issues/5851
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare QuickGrid di Blazor con Entity Framework
Hosting di componenti WebAssembly in un'applicazione Blazor static
Sfruttare gli embedding e la ricerca vettoriale con Azure SQL Database
Implementare l'infinite scroll con QuickGrid in Blazor Server
Esportare ed analizzare le issue di GitHub con la CLI e GraphQL
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Utilizzare il trigger SQL con le Azure Function
Evitare (o ridurre) il repo-jacking sulle GitHub Actions
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Eseguire operazioni sui blob con Azure Storage Actions
Sfruttare i KeyedService in un'applicazione Blazor in .NET 8
Migliorare l'organizzazione delle risorse con Azure Policy
I più letti di oggi
- Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
- Creare una libreria CSS universale: Cards
- Eseguire script pre e post esecuzione di un workflow di GitHub