Lo scopo di questo articolo è quello di comprendere cosa sono i memory leak in un’applicazione front-end e come individuarli con Google Chrome Dev Tools. E’ importante comprendere subito che Google Chrome Dev Tools è utile per misurare le performance del codice presente sul browser e non nel back-end dell’applicazione. Ricordiamo che Sme.UP ERP è composto da diversi strati.

Flusso delle informazioni su SmeUP ERP

Vediamo, in modo molto semplificato, il flusso delle informazioni tra i vari strati in un esempio di una richiesta di una griglia contenente l’elenco degli ordini di acquisto.

A scopo dimostrativo, supponiamo di avere un link nella pagina web con il testo “Mostra Ordini di Acquisto”. Una volta cliccato questo link, il programma deve mostrare gli ordini ai fornitori nello spazio sottostante il link. Vediamo di seguito i passaggi che vengono eseguiti attraverso tutti gli strati dell’applicazione:

  • Il browser fa la richiesta HTTP (in questo caso una GET tramite una chiamata ajax con Javascript) verso WebUP (scritto in java) attraverso l’Application Server (Payara) delegato ad intercettare tutte le richieste HTTP.
  • Web.UP riceve la richiesta e la gira ad uno strato di Middleware chiamato Provider. Il provider provvede a virtualizzare l’accesso ai dati e rende l’applicazione multi connessione. Web.UP non accede mai direttamente ai dati, ma lo fa sempre attraverso servizi. Per far ciò, esegue a sua volta una richiesta HTTP verso il Provider (anche in questo caso una GET ma tramite un client HTTP di Java).
  • Il provider riceve la richiesta HTTP ed esegue una FUN (ossia una richiesta di esecuzione di un programma) verso il back-end (nel nostro caso un AS400 con Sme.UP ERP) che a questo punto inverte il flusso restituendo i dati in formato XML al provider.
  • Il provider restituisce i dati a Web.UP.
  • Web.UP riceve l’XML, lo “parsa“, crea gli oggetti che rappresentano il modello di business e li collega alla pagina web. Quest’ultima operazione è quella che renderizza o per meglio dire, trasforma i dati in forma grafica creando il tag HTML da mettere nella pagina web.

Struttura alternativa dell’applicazione

Il primo e l’ultimo punto del paragrafo precedente sono quelli fondamentali per lo scopo di questo documento, quindi approfondiamo il concetto. La struttura a strati, di cui abbiamo accennato sopra, è utile per virtualizzare e disaccoppiare grafica, servizi e dati.

Una versione semplificata e meno astratta dell’applicazione potrebbe essere quella di creare una pagina web con un semplice tag <a> (link) ed un tag <table> (tabella). Cliccando sul link,  si richiama una funzione Javascript che esegue direttamente la richiesta dei dati al database (ad esempio as400) tramite una chiamata Ajax. Ricevuti i dati, Javascript scrive tanti tag <dr> (riga) e <dt> (colonna) contenenti i dati, quanti sono i record ricevuti. A questo punto il flusso si conclude.

JSF (Java Server Faces)

Per questi motivi Web.UP si avvale di JSF, una tecnologia java il cui scopo è quello di semplificare lo sviluppo dell’interfaccia utente di un’applicazione web. Può essere considerata a tutti gli effetti un Framework per componenti lato server di interfaccia utente.

JSF ha quindi lo scopo di creare la pagina web ad alto livello che viene renderizzata quando arriva sul browser. In poche parole, i tag HTML vengono effettivamente creati solo quando Java restituisce il risultato della richiesta. La cosa importante da comprendere, è che nella pagina che viene restituita, vi sono, oltre al risultato della richiesta, anche i link che possono eseguire altre richieste successive. Prendiamo ad esempio la pagina iniziale che contiene il nostro link  “Mostra Ordini di Acquisto”. Questa pagina, è stata fornita da JSF  da una richiesta precedente. Nella definizione di questo link, JSF ha già agganciato lo script Javascript con la richiesta Ajax ,che deve essere eseguita una volta cliccato.

Seguendo questo concetto, è chiaro che il lavoro di WebUP che viene fatto sul browser è interamente delegato a JSF.

Comprendere il funzionamento di una tecnologia come JSF esula dallo scopo di questo documento, ma è importante capire che ogni evento nel browser è effetto di Javascript e descritto tramite HTML. Nel caso di WebUP, vengono gestiti da JSF. Ovviamente c’è anche del codice Javascript,  scritto da Smeup.

Per quanto riguarda invece gli altri strati dell’applicazione come la parte di WebUP gestita dall’application server, il provider o la parte di back-end del database, ci sono altri strumenti per misurare le prestazioni che non saranno presi in considerazione in questo documento.

Anche per quanto riguarda il browser ci sono molti strumenti. Google Chrome Dev Tools è uno strumento molto veloce e facile da gestire.

Le referenze

In certi casi le informazioni delle pagine web (tag HTML, classi Javascript, dati etc..) vengono “trattenute” nella memoria heap senza che possano essere distrutte dal Garbage Collector di Javascript causando un “memory leak”.

Immaginiamo di avere una pagina web che contiene degli elementi HTML ed una classe di cui creiamo una referenza “A”. In questa pagina web abbiamo un link ad un’altra pagina che crea la referenza B di un oggetto che utilizza la referenza A creata in precedenza. Si viene a creare una catena di referenze. Quando la seconda pagina viene presentata video, Javascript “trattiene” anche la referenza A e con essa anche tutti gli elementi HTML della prima pagina che la utilizzano.

Javascript garbage collector (GC)

Come molti linguaggi di programmazione, anche Javascript possiede un Garbage Collector che ha il compito di eliminare dalla memoria heap del client dove risiede il browser, tutte ciò che non viene più utilizzato. Se non ci fosse il GC, ogni volta che visualizziamo una pagina web, il suo contenuto concorrerebbe a saturare la RAM fino al blocco dell’applicazione (out of memory).

Per poter eliminare il GC deve verificare prima che gli oggetti che fanno parte della catena delle referenze non siano più utilizzati. Nel nostro esempio, dovremmo: prima impostare come “undefined” la referenza B e di seguito la referenza A. In questo modo, al primo giro di controllo, il GC si rende conto che la referenza originale non è più utilizzata e quindi può eliminare tutto dalla memoria. Il GC si crea una mappa di referenze alla cui base c’è quello che viene chiamata “root” (radice).

Per far questo, il GC utilizza l’algoritmo “mark and sweep” che prevede 2 fasi:

  • Individuare gli oggetti non più referenziati costruendo una mappa delle dipendenze. (MARK)
  • Distruggere gli oggetti non utilizzati, eliminandoli dalla memoria, quando nessun’altra referenza vi fa riferimento. (SWEEP)

Cos’è un memory leak

In certi casi il GC non riesce ad eliminare una referenza perché questa contiene a sua volta una referenza che non è stata annullata oppure è ancora presente in qualche elemento HTML. I classici casi di memory leak sono i seguenti:

  • Aggiunta di un evento (addEventListener) senza averne effettuato la rimozione (removeEventListener)
  • Definizione di un oggetto come data nel dom (il documento web)
  • Mancata eliminazione di un oggetto dalla cache globale
  • “console.log” con oggetti che quindi vengono trattenuti in memoria

In questi casi, è utile l’apporto di uno strumento di misurazione delle performance come Google Chrome Dev Tools.

Google Chrome Dev Tools

Google Chome Dev Tools da la possibilità di individuare i memory leak con diversi strumenti:

  • Allocation Profiles
  • Heap Snapshots
  • Allocation Timelines

Per presentare tutti questi casi, a scopo dimostrativo, prenderemo come esempio una funzione di WebUP e vedremo le diverse informazioni con i vari strumenti. La funzione che utilizzeremo è il “todo”. Eseguiremo le seguenti operazioni:

  • conferma della funzione “todo” nello spotlight
  • click sul radio-button “Da assegnare”
  • click su di un todo per entrare in modifica
  • chiusura del dialog di modifica

 

Nella seconda parte di questo articolo spiegheremo più nel dettaglio questi strumenti che ci permettono di individuare i memory leak.