Con l'introduzione del web 2.0 e delle tecnologie Client denominate asincrone per la loro tipologia di esecuzione, abbiamo iniziato ad accantonare e a non tener in considerazione, le prestazioni del nostro codice. Una delle regole fondamentali di tutte le tecnologie web è sempre stata quella di tener bene in considerazione le prestazioni delle pagine.
Lo scopo di questo articolo è quello di capire come poter calcolare, con gli strumenti messi a disposizione dal Framework .NET, il tempo di richiesta ed esecuzione di una pagina. Renderemo il tutto modulare, in questo modo potremo sfruttare questa opzione in tutte quelle pagine che vogliamo monitorare.
Una pagina ASP.NET, così come un controllo o una webPart, sono composti da diversi eventi che rappresentano la loro creazione ed esecuzione. Così come esistono diversi eventi, esistono diverse tipologie di calcoli che possiamo effettuare. Vediamo cosa dice MSDN:
- Tempo di risposta: è la differenza di tempo che intercorre tra la richiesta e la restituzione del primo byte al Client. Questo è il valore che noi dobbiamo calcolare, poichè è quello percepito dall'utente.
- Tempo di esecuzione: tempo necessario a elaborare una richiesta, normalmente misurato tra il primo e l'ultimo byte restituiti al client dal server.
Vogliamo creare un componente riusabile, che diventi lo strumento per misurare l'esecuzione di una qualsiasi pagina ASP.NET. Per fare ciò utilizziamo un HttpModule
, implemendando l'interfaccia IHttpModules
. Implementando un modulo HTTP possiamo intercettare gli eventi che scaturiscono durante l'esecuzione di una applicazione Web. Per ereditare l'interfaccia dobbiamo necessariamente implementarne due metodi virtuali Init()
e Dispose()
.
Listato 1. Implementare l'interfaccia IHttpModule.
public class Modulo : System.Web.IHttpModule
{
public void Init(HttpApplication context) {
// da implementare
}
public void Dispose() {
// da implementare
}
}
Una volta messe le basi per la nostra classe, dobbiamo decidere quali eventi della pagina vogliamo intercettare e gestire. Vogliamo conoscere il tempo di esecuzioe di una pagina, quindi potremmo prendere come riferimento due eventi come estremi dell'intervallo di tempo:
- PreRequestHandlerExecute che avviene ad ogni richiesta da parte del Client
- PostRequestHandlerExecute viene invece rilasciato dalla pagina, quando è stata completamente processata
Prima di realizzare il codice della classe che rilevi il tempo trascorso tra i due eventi, fermiamoci un momento per pensare a come indicare al Web Server (IIS) la presenza di questo nuovo modulo. Per farlo dobbiamo definire il modulo nel "web.config" dell'applicazione, questa dichiarazione permette al modulo di essere rilevato e funzionare per tutte le richieste.
Osserviamo allora il codice necessario per registrare un HttpModule, sia per IIS 6 (e precedenti), sia per IIS 7, presente su Vista e Windows Server 2008.
Listato 2. Registrare l'HTTPModule
<!-- Sezione per IIS 6.0 e precedenti //-->
<system.web>
<httpmodules>
<add name="Modulo" type="HMod.Modulo"/>
</httpmodules>
</system.web>
<!-- Sezione per IIS 7.0 //-->
<system.webServer>
<modules>
<add name="Modulo" type="HMod.Modulo"/>
</modules>
</system.webServer>
Adesso che abbiamo definito la situazione, non ci resta che lavorare con i due eventi sopra citati. Per prima cosa, dobbiamo costruire gli Handler per questi eventi, nella nostra classe personalizzata.
Una volta costruiti dobbiamo registrarli, nell'evento Init del modulo, che avviene durante l'inizializzazione dell'applicazione Web.
Listato 3. Registrazione degli eventi nel modulo
public void Init(HttpApplication context)
{
// registrazione degli handler
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
// Inizio richiesta
}
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
// Fine richiesta
}
Adesso non dobbiamo far altro che decidere come calcolare i valori e successivamente, come andarli a leggere, e per lo meno, come visualizzarli nelle pagine.
Il calcolo è davvero molto semplice. Possiamo pensare di tenere traccia di un istante iniziale usando un oggetto di tipo DateTime
che dichiariamo come variabile privatadella classe.
Quando viene invocato il gestore dell'evento "Pre" registriamo l'istante iniziale prendendo il momento corrente della richiesta.
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
istanteIniziale = DateTime.Now;
}
Alla fine della richiesta viene invocato il secondo evento, "Post". Qui creiamo una variabile di tipo TimeSpan
che conterrà la differenza tra l'istante attuale (ovvero quello finale) e l'istante iniziale che avevamo registrato in precendenza
Una volta trovato il tempo, dobbiamo caricarlo nella pagina. Possiamo farlo tramite Javascript, perchè a questo punto ASP.NET ha concluso il suo ruolo. In alternativa possiamo registrare il valore in un file di log per effettuare delle statistiche.
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
TimeSpan tempoTrascorso = DateTime.Now - tempo;
// passaggio del valore alla pagina
}
Nel nostro esempio, abbiamo utilizzato un <div>
con due controlli da inserire in ogni pagina. Una funzione JavaScript modifica una label all'interno del livello.
Conclusioni
Lavorando con i Moduli Http, è opportuno rendere il codice il più possibile modulare, quindi è meglio non usare sessioni che potrebbero essere ancora disattive o altre caratteristiche troppo legate alla pagina.