Per realizzare applicazioni che rendano i nostri utenti entusiasti, non dobbiamo solo fare in modo che il nostro codice "funzioni" ma dovremmo anche garantire buone performance e pagine che si caricano rapidamente. Oltretutto, se realizziamo un'applicazione che esige poche risorse dal server, aiuteremo il nostro committente a ridurre i costi di funzionamento.
MiniProfiler è uno strumento che può aiutarci a realizzare questi obiettivi, perché serve a "profilare", cioè esaminare il comportamento della nostra applicazione per produrre un report HTML, compatto ma informativo, che rende evidenti le possibili inefficienze della nostra applicazione.
Con esso possiamo tracciare sia i tempi di esecuzione delle nostre routine che il numero di query SQL che inviamo al database.
Installare MiniProfiler
Iniziamo installando i pacchetti di MiniProfiler con i seguenti comandi. Il primo pacchetto è strettamente necessario, mentre il secondo lo referenziamo solo se nella nostra applicazione stiamo usando Entity Framework Core.dotnet add package MiniProfiler.AspNetCore.Mvc
dotnet add package MiniProfiler.EntityFrameworkCore
Poi rechiamoci nel metodo Configure della classe Startup e configuriamo il middleware di MiniProfiler.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiniProfiler();
//Qui usiamo altri middleware
}
Restiamo nella classe Startup e andiamo anche ad aggiungere i suoi servizi nel metodo ConfigureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddMiniProfiler()
.AddEntityFramework(); //Aggiungiamo questa riga solo se usiamo Entity Framework Core
//Qui aggiungiamo altri servizi
}
MiniProfiler dispone di tante opzioni di configurazione che possiamo fornire al metodo AddMiniProfiler. Ad esempio possiamo decidere selettivamente quali richieste profilare e come vogliamo che siano mostrate le informazioni. Tutto ciò lo troviamo documentato all'indirizzo https://miniprofiler.com/dotnet/AspDotNetCore
Per completare l'installazione, apriamo la view /Views/Shared/_Layout.cshtml e inseriamo il tag helper di MiniProfiler, che verrà usato per sovraimporre il report HTML alle nostre view. Posizioniamolo subito prima della chiusura del tag .
<!DOCTYPE html>
<html>
<head>
<!-- Omissis -->
</head>
<body>
<!-- Omissis -->
<mini-profiler />
</body>
</html>
Infine andiamo in /Views/_ViewImports.cshtml e registriamo il tag helper in modo che possa essere elaborato dal view engine Razor.
@addTagHelper *, MiniProfiler.AspNetCore.Mvc
Ora siamo finalmente pronti per iniziare a profilare la nostra applicazione ASP.NET Core.
Profilare le query LINQ di Entity Framework Core
Supponiamo di voler verificare il comportamento di una query LINQ che estre alcuni prodotti e da cui selezioniamo la categoria. Per profilare il codice, avvolgiamolo con l'istruzione MiniProfiler.Current.Step("Descrizione").using (MiniProfiler.Current.Step("Recupero categorie"))
{
var categories = new HashSet<Category>();
//db è un riferimento all'istanza del nostro DbContext
var products = await db.Products.Where(p => p.Amount > 1000)
.ToListAsync();
foreach (var product in products)
{
categories.Add(product.Category);
}
}
Se abbiamo il lazy loading abilitato, questo codice produrrà numerose query al database: una per recuperare i prodotti e altre n per recuperare la categoria di ciascun prodotto. Questo è anche noto come problema Select n+1 e potrebbe passare inosservato se non prestassimo attenzione alle query inviate da Entity Framework Core. Con MiniProfiler, il problema risulta subito evidente perché nella ci mostra una linguetta nella parte alta a sinistra della pagina. Essa riporta il tempo di esecuzione con un punto esclamativo, a segnalare una situazione anomala. Lo possiamo cliccare per avere dettagli aggiuntivi e scoprire che in questo caso stiamo inviando ben 38 query SQL, come si nota dall'immagine.

Cliccando il 38 possiamo entrare nel dettaglio per scoprire quali sono le query in questione. Qui sono anche evidenti i momenti in cui apriamo e chiudiamo la connessione.

Comprendere il problema è solo il primo passo ma ci mette in condizione di pensare a una soluzione migliore, che in questo caso consiste nel modificare la query LINQ così.
var categories = await db.Products.Where(p => p.Amount > 1000)
.Select(p => p.Category)
.Distinct()
.ToListAsync();
Profilare le query di ADO.NET
Anche usando ADO.NET possiamo sfruttare MiniProfiler per misurare il tempo di esecuzione delle query. Per attivare il profiler, in questo caso dobbiamo anche crearci un oggetto StackExchange.Profiling.Data.ProfiledDbConnection e passargli la connessione nel costruttore, come si vede nel seguente esempio.using (MiniProfiler.Current.Step("Query ADO.NET"))
{
using (var conn = new StackExchange.Profiling.Data.ProfiledDbConnection(
new SqlConnection(connString), MiniProfiler.Current))
{
await conn.OpenAsync();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT * FROM Products, Categories WHERE Products.Amount > 1000";
using (var reader = await cmd.ExecuteReaderAsync())
{
//Omissis
}
}
}
}
In questo caso vediamo appunto che la query (una CROSS JOIN non corretta) sta richiedendo più di 1 secondo e quindi dovremmo valutare se abbiamo risultati migliori da una LEFT JOIN e dall'aggiunta di indici.

Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Esporre i propri servizi applicativi con Semantic Kernel e ASP.NET Web API
Loggare le query più lente con Entity Framework
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Recuperare App Service cancellati su Azure
Generare un hash con SHA-3 in .NET
Gestire i dati con Azure Cosmos DB Data Explorer
Anonimizzare i dati sensibili nei log di Azure Front Door
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Documentare i servizi REST con Swagger e OpenAPI con .NET 9
Generare HTML a runtime a partire da un componente Razor in ASP.NET Core
Recuperare automaticamente un utente e aggiungerlo ad un gruppo di Azure DevOps
Ottenere un token di accesso per una GitHub App
I più letti di oggi
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- #lightswitch 2012 supporta nativamente #html5, #jquery e #jquerymobile. è stato mostrato girare su #ipad a #msteched
- 6 giorni al lancio di #netfx4 e #vs10ita. segui il nostro speciale su http://u.aspitalia.com/gh