Archive for 28/01/2018

Tuning applicativo

Chi ha esperienza nello sviluppo di applicazioni, soprattutto quelle gestionali, sa che spesso, dopo aver raggiunto l’obbiettivo iniziale di coprire gli aspetti funzionali indicati dalla fase di analisi, si rende prima o poi necessaria una fase di tuning applicativo.

Si cercano le possibili risposte alla domanda: come faccio a far fare alla mia applicazione le stesse cose che fa oggi ma più velocemente?
Si identificano i punti maggiormente critici e poi si procede…

In genere la tecnica chiave utilizzata è quella di evitare accessi ricorsivi al database lavorando su aree di memoria di processo opportunamente predisposte; alcuni giorni fa attuando su un caso specifico questa tecnica abbiamo sfruttato a fondo le liste Uniface associative (chiave=valore) con un metodo che potrebbe tornare utile in molte occasioni.

Si dovevano ottimizzare le funzionalità del ciclo attivo in una installazione gestionale che lavora su una anagrafica di circa 100.000 articoli; utilizzando il profiling applicativo, messo a disposizione da Uniface, abbiamo dapprima determinato che il punto critico in tutte le funzionalità del ciclo attivo era la determinazione di prezzo di vendita/sconti quantità, perché era costituita da un algoritmo multi-livello che doveva tenere in considerazione:
– listino standard
– listino tra quelli disponibili applicato al cliente
– campagne tra quelle disponibili applicabili al cliente
– promozioni tra quelle disponibili applicabili al cliente
– prezzi speciali ammessi per il cliente

A fronte di una ricerca articoli la determinazione di prezzo/sconti per quel cliente di ogni articolo al “momento” richiedeva con l’algoritmo multilivello circa 0.8 secondi. Non molto in valore assoluto ma un valore comunque impattante rispetto alla usabilità delle funzionalità del ciclo attivo in una schermata che presenta diversi articoli.

Abbiamo provato a trovare il miglioramento ricercato evitando di andare sul database per ogni articolo alla ricerca del prezzo da applicare ma cercandolo in memoria; la predisposizione della ricerca in memoria è stata fatta in questo modo:
1) Popolando all’ingresso della funzione applicativa una area di lavoro associata alla sessione applicativa (nel nostro caso NodoRete+IDprocesso)
2) Inserendo sull’area di lavoro TUTTI gli articoli che il cliente del momento può acquistare dal listino standard
3) Aggiornando gli articoli nell’area di lavoro per listino cliente, campagne, promozioni e prezzi speciali validi per il cliente del momento
4) Caricando in memoria il risultato finale ottenuto sull’area di lavoro: l’insieme completo degli articoli vendibili a quel cliente in quel momento comprensivi di prezzo e sconti quantità.
Questa parte di funzionalità è stata inserita all’inizio nella gestione offerte e nella gestione ordini clienti, subito dopo aver identificato il cliente, in modo da poter applicare tutte le regole del business necessarie per ogni specifico cliente; avviando le suddette funzioni applicative senza identificazione di un cliente specifico, viene caricato il contesto di vendita per un cliente generico, senza particolari facilitazioni economiche. Il caricamento in memoria richiede complessivamente da 3 ai 6 secondi (in funzione del cliente) all’avviamento della corrente funzione applicativa e utilizza in tutto solamente qualche MB (100.000 x 35bytes = 3,5 MB).

Come conviene costruire la matrice in memoria?
L’ideale sarebbe una lista associativa (chiave=valore) per poter sfruttare a fondo il linguaggio ProcScript disponibile in Uniface; per costruirla velocemente sono necessari due passaggi con il seguente snippet di codice:
– sql/data “select campo/iChiave,’=’,attributo/iNecessari from AreaDiLavoro where IDsessione=%%vSessione%%%”, “DEF”
– $$Matrice = $replace($result,1,”!;=!;”,”=”,-1) ; != è uguale a <GOLD>!<GOLD>;
Con queste due semplici istruzioni ci ritroveremo in memoria una lista Uniface di tipo associativo (chiave=valore) con un costrutto riconducibile al seguente:
ARTICOLO1=PREZZO1;SCONTO1.1;SCONTO1.2;SCONTO1.3
ARTICOLO2=PREZZO2;SCONTO2.1;SCONTO2.2;SCONTO2.3
avendo così la possibilità mediante il semplice utilizzo di quest’altra istruzione del ProcScript:
– attributiArticolo = $item(“ARTICOLO1”, $$Matrice)
di ritrovarci in attributiArticolo una lista posizionale contenente:
PREZZO1;SCONTO1.1;SCONTO1.2;SCONTO1.3
e potendo successivamente recuperare le singole componenti in modo posizionale:
– getitem vPrezzo, attributiArticolo, 1
– getitem vSconto1, attributiArticolo, 2
– getitem vSconto2, attributiArticolo, 3
– getitem vSconto3, attributiArticolo, 4
La risoluzione in memoria degli attributi di 1000 articoli random da una matrice che ne comprende 100.000 con copia del risultato ottenuto sulla MessageFrame di Uniface richiede solamente una ventina di centesimi di secondo: praticamente istantanea!

Il limite di questo approccio è ovviamente il fatto che NON è possibile aggiornare con un’altra sessione applicativa un singolo prezzo per il cliente del momento e vederlo utilizzato immediatamente; è necessario uscire e rientrare nella funzione che utilizza il metodo descritto per vedere aggiornati i prezzi utilizzati…ma è una approssimazione accettata nella quasi totalità delle aziende.

Chi volesse approfondire mi contatti a gianni.sandiglianoATunifacesolutions.com.

Gianni