You are on page 1of 10

ANALISI PRESTAZIONALE APPLICAZIONE GRAILS

Descrizione Applicazione e Tecnologie utilizzate

L’applicazione oggetto del test è stata realizzata in Grails 1.3.6, per il database è stato utilizzato
MySQLServer 5.0. Il DB consta di tre tabelle (utente, proprietario, auto), ma in fase di test ne sono
state utilizzate solo due (Utente per la login, proprietario per l’aggiunta di un nuovo record e per la
lista).
Il deploy dell’applicazione è stato fatto su Apache Tomcat 6.0 residente su una workstation
Window XP, la stessa su cui è presente il DB.
I test sono stati effettuati da PC remoti utilizzando una LAN isolata, per evitare che i risultati
potessero essere falsati da un sovraccarico del traffico di rete.
Per il monitoraggio del comportamento dell’applicazione è stato utilizzato JMeter 2.4

Configurazione Apache Jmeter

JMeter è tool opensource sviluppato dalla Apache Software Foundation che permette di effettuare
test di carico di qualsiasi tipologia di software, comprese le Web Applications. È possibile simulare
la concorrenza attraverso i Threads permettendo quindi di misurare la performance al variare del
carico attraverso la generazione di valori statistici come la media, la mediana, la varianza e il
throughput.

È possibile scaricare l'ultima versione stabile (2.4) dal sito ufficiale


http://jakarta.apache.org/jmeter/. Per lanciare il programma è necessario eseguire il file
jmeter.bat presente nella cartella bin.

Prima di tutto bisogna creare un Test Plan che descrive gli step da seguire per l'esecuzione del
Test. È possibile configurare i seguenti parametri:
 Name: ciascun piano di test viene identificato con un nome
 User Definned Variables: è possibile associare al piano di test n variabili che possono
essere richiamate all'interno del test;
 Run Thread Group consecutively: è possibile stabilire se i thread (utenti virtuali) devono
essere avviati in modalità sequenziale (al termine di un thread viene avviato il successivo)
oppure in modalità parallela (viene lanciato il primo, dopo k secondi viene lanciato il
secondo, dopo 2k secondi il terzo e così via);
 Library: è possibile aggiungere delle classi o dei pacchetti jar al classpath.

Nei test effettuati si è provveduto solamente a specificare il Name, che comparirà nel menù ad
albero sulla sinistra, lasciando invariate le altre opzioni.
Cliccando con il tasto destro del mouse sul nome del nostro Test Plan possiamo iniziare ad
aggiungere un Thread Group, l’elemento che conterrà tutti gli altri. Una volta specificato il nome si
va a configurare le seguenti proprietà:

 Numero di Threads, che simulano l'accesso contemporaneo di un numero variabile di


utenti
 Ramp-up period, il tempo massimo che intercorre dall'avvio del primo thread all'avvio
dell'ultimo
 Loop Count, ovvero il numero di volte che deve essere eseguito il test dallo stesso Thread: in
questo caso si può anche simulare un loop infinito, od eventualmente schedulare start e
stop del test.

Una volta aggiunto un Gruppo di Thread, con una procedura analoga, possiamo impostare un
Config Element di tipo HTTPRequestDefault.
Dopo aver specificato il nome dell’ HTTPRequestDefault andremo ad inserire i parametri di
connessione del server su cui gira l’applicazione da testare, cioè l’indirizzo e la porta
A questo punto possiamo aggiungere le HTTPRequest che ci interessano, sempre con il solito
sistema, tasto destro sul Thread Group Add->Sampler->Http Request.

In questa finestra sarà possibile impostare i seguenti parametri principali:

- Name: identificativo della richiesta nel menu;


- Server Name o IP e numero di Porta: nome del server o IP e porta alla quale connettersi; in
tal caso possiamo omettere di specificare questi parametri in quanto in precedenza abbiamo
configurato l’HTTPRequestDefault cui faranno riferimento tutte le nostre Request;
- Method: metodo GET o POST con il quale inviare la richiesta;
- Path: risorsa del server da richiamare;
- Parameters: parametri da passare nella richiesta.
Nel test sulla nostra applicazione abbiamo preso in considerazione il seguente flusso:
1. Accesso ad una pagina di autenticazione.
2. Inserimento delle credenziali di accesso con passaggio di due parametri (username e
password) con forward su una pagina di menu
3. Accesso ad una pagina che presenta una lista di record presenti su DB, nel nostro caso
Proprietari
4. Accesso alla pagina che permette l’inserimento di un nuovo record
5. Inserimento del nuovo record con passaggio di tre parametri (nome, cognome, nazionalita)
con forward su una pagina di riepilogo
6. Nuovo accesso alla pagina con la lista dei record

Per ogni step del flusso è stata creata un HTTPRequest, in modo tale da monitorare ogni
passaggio.

L’ultima operazione da effettuare è la scelta dei Listener, che ci permetteranno di leggere i risultati
del test secondo parametri e visualizzazioni diverse. Nel nostro caso abbiamo utilizzato i seguenti:
- View Result Tree che riassume tutte le richieste e risposte HTTP eseguite durante il test. Per ogni
Thread viene visualizzato l’esito della richiesta con relativa descrizione dettagliata.
- View Result in Table, in cui l’esito delle richieste di ogni Thread è visualizzato in tabella con
minor dettaglio di informazioni.
- Graph Result, che permette di visualizzare il grafico dell’intero test per quanto riguarda
Throughput, Media, Mediana e Deviazione Standard
- Aggregate Graph, che riassume i dati totali e per singola HTTPRequest in una tabella, dando
anche la possibilità di costruire grafici per valutare i tempi di risposta.

Una volta configurati i Listener possiamo far partire il test dalla voce di menu Run -> Start, o
alternativamente la combinazione di tasti CTRL+R. Per arrestare il test Run -> Stop o
alternativamente la combinazione di tasti CTRL+. .

Risultato dei Test


Sono stati compiuti vari test di carico su di un’applicazione Grails variando il numero di utenze, il
tempo di Ramp-up degli user e il numero di loop count.
Le unità di misura dei test che sono stati compiuti sono le seguenti:
Throughput: Request/sec, KB/sec;
Tempo: ms(millisecondi);
Il primo test è stato effettuato cambiando il numero di utenze ma mantenendo il tempo di Ramp-
up a un secondo e il loop count a 1.
Si è notato che da 1 a 10 utenze si ha un incremento del throughput notevole mentre il tempo di
esecuzione di ogni thread si è mantenuto costante; mentre da 10 a 140 utenze si mantiene un
throughput abbastanza stabile tra le 40 e le 50 request/sec mentre si ha un incremento in maniera
costante del tempo di esecuzione di ogni thread (come si può notare dal grafico sottostante). Oltre
le 140 utenze abbiamo costatato che alcune request non erano eseguite poiché era lanciata
un’eccezione:
“java.net.ConnectException: Connection refused: connect”;
la percentuale di questa eccezione aumentava all’aumentare delle utenze che si connettevano.

Figura 1 - Curva che rappresenta il throughput al variare delle utenze con un Ramp-up a un secondo.

Figura 2 - Curva che rappresenta la durata media di ogni ciclo del thread.

In questo test il throughput KB/sec si è mantenuto stabile a circa 270,00 KB/Sec.


Il secondo test effettuato si è modificato il numero di Ramp-up portandolo a 2 secondi mentre si
sono lasciati i loops counts a 1 e sono stati variati solamente il numero di utenze.
Qui mentre con un’utenza si ha un comportamento costante, con 2 utenze abbiamo un minimo
della curva; mentre da 2 a 10 utenze si ha un valore costante del tempo del thread mentre si ha
una crescita esponenziale del throughput medio; invece i valori fra 10 e 150 utenze si ha una
stabilizzazione del throughput ma una crescita del tempo medio di ogni thread. Una differenza che
è stata notata è che il lancio dell’eccezione si è cominciato a costatare oltre le 150 utenze.

Figura 3 – Rapporto throughput/utenze con un Ramp-up a 2 secondi

Figura 4 – Cambiamento del tempo medio di esecuzione del thread.

Anche qui si è notato che il throughput KB/sec rimane costante per tutti i test effettuati a un
valore medio di circa 275-280 KB/sec.
Nel terzo test effettuato abbiamo portato il valore di Ramp-up a 5 secondi.
Il throughput da 1 a 5 utenze scende molto, mentre da 5 a 50 utenze si ha un nuovo aumento di
valore fino a assumere un andamento che si può definire costante fra le 50 e le 200 utenze. Il
tempo di esecuzione del thread medio rimane costante in relazione ai due test di prima, da 1 a 10
utenze si ha un tempo di esecuzione costante valorizzato a circa 33 ms, mentre da 50 a 200 utenze
si ha un incremento proporzionato. In questo caso l’eccezione viene lanciata oltre le 200 utenze.

Figura 5 – Grafico con Ramp-up di 5 secondi

Figura 6 – Rappresentazione dell’incremento della durata media di ogni thread.

Il throughput medio in KB/sec in questo test si è stabilizzato a circa 280-285 KB/sec.


Nell’ultimo test effettuato si sono incrementati i loop-counts a 10 cicli mentre è stato lasciato
costante il valore di Ramp-up.
Possiamo notare che il throughput si stabilizza subito, anche con una singola utenza, oltre le 40
request/sec per rimanere costante fino a 150 utenze, valore per cui il server lancia l’eccezione.
Mentre il tempo di esecuzione dei thread si incrementa in maniera costante.

Figura 7 – Throughput medio con loop-count impostato a 10

Figura 8 – Tempo medio dell’esecuzione dei thread.

In questo test il throughput rimane stabile fra i 290 e i 300 KB/sec.


Conclusioni
In tutti i test effettuati abbiamo riscontrato delle risposte simili sia per quanto riguarda il
throughput,che oltre i 10 accessi si stabilizza intorno alle 50 request al secondo, sia per quanto
riguarda il tempo medio di esecuzione del thread. Inoltre il sistema rimane stabile fino alle 150
utenze contemporanee circa: superata questa soglia il web server comincia a lanciare delle
eccezioni dovute al sovraccarico di richieste.

Dopo aver effettuato diversi test si è constatato che sulle prestazioni dell’applicazione non incide
tanto il traffico di rete, quanto la mole di dati presente sul DB. A tal proposito non abbiamo
riscontrato rilevanti differenze tra i risultati dei test effettuati su LAN aperta e quelli effettuati su
LAN isolata. Al contrario abbiamo assistito ad un calo delle performance man mano che si riempiva
il DB: già con tabelle di 1000 record il throughput medio subiva un incremento del 5%. Vista
l’incidenza del riempimento delle tabelle sulle prestazioni dell’applicazione, si è provveduto a
svuotare il DB ogniqualvolta ci si avvicinava ai 5000 record scritti.