Metti che prendi un IBM Power8 per risolvere tutti i tuoi problemi

Di recente ho lavorato alla configurazione di un nuovo server baan IV con oracle. Si trattava del passaggio da un cluster con 2 server HP Integrity rx2660 con sistema operativo HP-UX B.11.31 e processore Intel Itanium 2 9140 (2 core, 1,66GHz, 4 logical CPU dovute all’attivazione dell’hyper-threading) con 32GB di RAM, ad un cluster con 2 server IBM 8286-41A con degli LPAR con sistema operativo AIX 7.1.3.45 TL03 e processore POWER8 (6 core dei quali solo 2 abilitati, 3,02GHz, quindi 2 virtual CPU con in tutto 4/8/16 logical CPU configurabili con SMT) con 32GB di RAM.

Sul vecchio sistema era utilizzato oracle 10g (10.2.0.4.0 standard edition), sul nuovo è stato scelto oracle 12c (12.1.0.1.0 standard edition) perché il vecchio 10g non è più supportato da oracle e non va su AIX 7.1. Come conseguenza dell’aggiornamento di oracle è stato aggiornato anche il porting set: dalla serie 6.1c alla 9.0, con conseguente attivazione del driver di baan per oracle in configurazione «combo».

Il server HP aveva un ambiente baan+oracle di produzione su una macchina del cluster, e un secondo ambiente baan+oracle di test sulla seconda macchina. Sul nuovo cluster, in un primo momento, è stato migrato solo l’ambiente di produzione configurando il cluster in modo tale che baan e oracle potessero andare su LPAR diverse o sulla stessa. Per questo motivo sul package di baan è stata installata anche una oracle home da usare per connettersi via SQL*Net (e tnsnames.ora) al database oracle.

L’installazione è stata fatta mantenendo i due package (oracle e baan) sullo stesso LPAR, ma nei primi giorni di lavoro si è capito che il nuovo server era lento, anche parecchio, se confrontato al vecchio. Una serie di analisi dettagliate hanno mostrato che le statistiche usate dall’ottimizzazione di oracle non erano aggiornate, difatti il job interno di oracle 12 che le aggiorna non era stato attivato. Il calcolo delle statistiche tramite DMBS_STATS.GATHER_SCHEMA_STATS(‘BAAN’) oppure tramite un ANALYZE TABLE BAAN.T… forniva lo stesso risultato: le prestazioni diventavano accettabili, ma la macchina era carica al 100% con un runqueue (mostrata da topas) di circa 30. È stato allora deciso di spostare il package con oracle sul secondo LPAR, in modo da avere a disposizione il doppio dei processori.

A questo punto nessuna delle macchine era carica al 100%, ma in ogni caso il sistema era lento tanto quanto prima. Per fare un esempio: il job dell’MRP durava 7 ore contro l’ora che impiegava sulla macchina HP. Il calcolo costi arrivava quasi a 12 ore contro soli 40 minuti. Oltre alla lentezza nei job, anche l’utilizzo OLTP mostrava lentezze esasperanti diffuse e generalizzate. Durante queste operazione la macchina non ha mai paginato, la quntità di memoria data ad oracle e chiamata SGA è sempre stata di circa 9Gb, la RAM veramente usata dalle applicazioni (secondo lo strumento nmon) è stata sempre attorno ai 22-23Gb rispetto ai 32Gb disponibili, l’I/O verso lo storage è sempre stato ottimo, il cache hit di oracle sempre superiore al 99,5%.

Come mai? Ah, già! Non abbiamo abilitato l’«array interface» di baan.

È stata allora abilitata — limitatamente ad un job daemon — l’«array interface»: 100 record alla volta sia per la lettura dei record durante le SELECT, sia per l’invio durante le INSERT. Il dettagli dei nuovi parametri è:
ora_init:0101000
ora_max_array_fetch:100
ora_max_array_insert:100
rds_full:100
ssts_set_rows:100
inoltre sono stati impostati STU e DTU da 8192 byte nel tnsnames.ora nonostante l’MTU sia sempre stato di 1500 byte.

Purtroppo, con l’array interface, i tempi non sono cambiati di una virgola.

Come mai? In effetti spulciando meglio tutta la documentazione relativa ai parametri SDU e TDU, si scopre che il beneficio nell’incrementarli si ha solo su linee lente, tipo la token ring, o la 10mbit/s, ma qui le due LPAR sono collegate su uno switch da 1gbit/s full duplex che vanifica l’utilizzo di SDU e TDU. Si potrebbe provare ad attivare i jumbo frame e aumentare l’MTU, ma questo comporta la riconfigurazione dello switch che non è immediata e non ha la certezza dell’incremento delle prestazioni. Invece l’«array interface» diminuisce veramente il numero dei roundtrip, quindi deve per forza aver portato un miglioramento delle prestazioni, ma evidentemente questo non è percepibile a causa di altri problemi decisamente maggiori.

A questo punto è stato eseguito il job dell’MRP con il profiler (Call Graph Profiler, CGP) di baan attivo. La documentazione dice che è disponibile solo su LN, ma non è vero: è disponibile solo con il porting set di LN, ma poiché qui usiamo il porting set di LN con baan IV, allora lo possiamo utilizzare. Oltre al CGP, è stato attivato anche l’SQL_TRACE in modo da avere tutte le misurazioni possibili sia lato baan che lato oracle. Il job è durato 2 ore in più a causa della profilazione, ma ha mostrato una grande discrepanza nei tempi che baan cataloga come attesa dei dati da oracle, e quelli che oracle sostiene di avere veramente impiegato. Se baan attende in tutto 7 ore da oracle, ma oracle sostiene di avere impiegato in tutto 40 minuti, allora il problema sta nel tempo impiegato nella comunicazione tra i due: baan attende che la sua richiesta vada ad oracle, che oracle produca dei risultati, che questi risultati tornino a baan; invece nel conto di oracle c’è il tempo dall’arrivo della richiesta di baan fino al momento dell’invio dei risultati. La differenza è il tempo di trasporto delle richieste e dei risultati.

Chiarito questo, è stato ipotizzato che il colpevole fosse SQL*Net, cioè il protocollo di rete di oracle. L’alternativa ad SQL*Net è BEQ, che però funziona solo su IPC e non su TCP/IP. quindi, per passare a BEQ è stato portato il package di oracle sulla stessa LPAR di baan ed è stato riconfigurato baan per comunicare tramite BEQ cioè: ORACLE_SID al posto di ORACLE_SERVICE_NAME e utilizzo della stessa oracle home dell’istanza.

Alla connessione degli utenti baan ad oracle si sono avuti gli errori ORA-01116 «error in opening database file». Questo problema è dovuto al fatto che i datafile di oracle sono adesso aperti dai processi client di utenti baan (del gruppo unix bsp), mentre prima tutti i file erano aperti dall’utente AIX oracle. Perché quest’ultimo potesse utilizzare datafile più grandi di 2Gb, gli sono state alzate le soglie massime in /etc/security/limits.conf, ma adesso i processi degli utenti baan non riescono ad aprire quei file perché la loro soglia è minore. Per risolvere questo problema, poiché non è possibile su AIX impostare i limiti per un gruppo (ad esempio, su Linux, si sarebbe potuto utilizzare il nome «@bsp» per assegnare i limiti a tutto il gruppo bsp) si è deciso di aumentare i limiti predefiniti di tutti gli utenti, equiparandoli a quelli precedentemente assegnati ad oracle. A quel punto è stato possibile collegarsi da baan ad oracle senza errori.

I tempi di esecuzione dei job sono tornati minimi: con l’«array interface» l’MRP gira in 45 minuti, il calcolo costi in 28 minuti (quest’ultimo ha impiegato 10 minuti di CPU nel processo audit_srv poiché la tabella degli articoli è sotto audit). Quindi la differenza tra SQL*Net e BEQ si è rivelata effettivamente enorme.

Nell’utilizzo durante la giornata, con pochi job e parecchi utenti, la macchina non sembrava particolarmente veloce e neppure lenta, ma era sempre carica al 100%. Per poter lavorare con un minimo di margine è stato proposto di attivare un terzo core della CPU, ma in questo caso si avrebbero avuti due problemi: il primo è che il costo delle licenze oracle standard edition sarebbero aumentate di 25000€, il secondo è che per poter aggiornare oracle alle prossime versioni è necessario passare gratuitamente alla standard edition two (SE2), oppure a pagamento alla enterprise edition, ma la SE2 impone il limite di 2 core e di 16 thread. Quindi l’abilitazione di un terzo core è una opzione scartata perché troppo costosa.

Come alternativa è stato modificato il numero di processori logici: l’LPAR ha assegnati due core, che dentro l’LPAR sono visti come CPU virtuali, che sono poi divisi in CPU logiche. Fino ad ora la divisione era in quarti: ogni CPU virtuale era divisa in 4, ma il power permette anche la divisione in 2 o in 8 diversi thread hardware. Sono quindi state fatte delle prove e si è visto che utilizzando la configurazione SMT8 (cioè 8 thread hardware per ciascuno dei due core della CPU, arrivando ad un parallelismo totale di 16) il sistema non era più costantemente carico al 100%, ma aveva un minimo di margine aggiuntivo che durante l’orario lavorativo era tra il 2 e il 7% (idle), mentre quando gli utenti italiani non lavoravano e restavano solo quelli stranieri (una quarantina compresi i job daemon), si arrivava al 10-20% di idle.

Come funziona, a grandi linee, questa cosa del numero di thread hardware: il singolo core del POWER8 è composto da vari componenti hardware che possono essere utilizzati per  «comporre» 2, 4 o 8 CPU logiche. L’hardware è sempre lo stesso, quindi se lo divido in 4 (configurazione SMT4), avrò delle CPU logiche che al massimo avranno 1/4 della potenza totale del core; se lo divido in 8 (configurazione SMT8) allora ogni CPU logica avrà la metà della potenza che avrebbe in SMT4, cioè 1/8 della potenza totale del core.

Come funziona la richiesta di potenza di calcolo di un normale processo baan: la bshell, cioè il processo del sistema operativo che contiene la logica di baan, esegue le sessioni di baan. Quando deve accedere al database, fa la richiesta ad oracle e attende la risposta. A quel punto sul sistema operativo la bshell non chiede più CPU, che viene invece richiesta dal processo oracle (che nella nostra configurazione è DEDICATED e non MTS, cioè c’è un processo oracle per ogni bshell). Quando oracle termina, restituisce alla bshell il risultato e non richiede più la CPU. A quel punto la bshell viene svegliata e riprende l’elaborazione con la CPU. Morale: pur avendo vari processi del sistema operativo, solo uno è attivo in un determinato momento, quindi un utente baan (o un job daemon) richiede al sistema esattamente una CPU.

Chiarito come funzionano SMT e la richiesta di CPU, vediamo i due scenari OLTP e batch:

  • durante la giornata ci sono decine di utenti collegati al sistema, e ciascuno di essi richiede la CPU per una semplice e veloce transazione (OLTP). AIX assegna la prima cpu logica libera alla bshell e ad oracle alternativamente. Poiché gli utenti sono decine, potrei utilizzare decine di CPU. In SMT4 il sistema aveva 4 CPU logiche per ciascuno dei due core, quindi con 8 CPU si vedeva che la macchina era satura al 100%. Difatti la percentuale TOTALE di CPU idle era 0. Invece, una volta configurato il processore in SMT8, il sistema AIX vedeva 16 CPU logiche, ma evidentemente le decine di utenti collegate al sistema non richiedevano la CPU con un grado di parallelismo 16, e quindi AIX poteva risparmiare un processore mostrando il sistema con un idle TOTALE del 7% che — guarda caso — è circa 1/16 di processore;
  • durante la notte il sistema si trasforma da OLTP a batch: non ci sono decine di utenti collegati, ma solo due job daemon, dei quali solo uno con i job impegnativi. Allora il lavoro notturno richiede una sola CPU. Nella configurazione in SMT4, i tempi di esecuzione dell’MRP e del calcolo costi era scesi a 3/4 dei corrispondenti tempi sulla macchina HP-UX. Ma poiché non c’erano altri processi a richiedere la CPU, il sistema mostrava una CPU al 100% e le altre 7 idle. Cioè il job stava sfruttando appieno una delle CPU logiche su un core in SMT4, cioè usava appieno il 25% di un core. Una volta riconfigurata la CPU in SMT8, lo stesso job ha usato la CPU logica al 100% lasciando le altre 15 CPU idle, vale a dire che ha usato al massimo 1/8 di core. E difatti, in SMT8, i tempi d’esecuzione dei job sono più che raddoppiati rispetto a SMT4: l’MRP dura circa 2 ore al posto di 45 minuti, il calcolo costi  1 ora e 45 al posto di 30 minuti. I tempi avrebbero dovuto solo raddoppiare, ma evidentemente le varie configurazioni SMT non seguono un andamento lineare.

Chiarito quindi che l’aver visto un po’ di CPU idle in SMT8 è stato solo un caso dovuto al fatto che in quel momento non era richiesto dal sistema un grado di parallelismo di 16, viene da pensare che in SMT8, poiché il 7% della CPU non era usata, gli altri 15 utenti che veramente stavano lavorando andassero leggermente più piano, difatti non potevano sfruttare quel 7%. Ma evidentemente la sensazione dell’utente non è così sensibile da accorgersene.

La soluzione finale sembra quella di configurare la macchina in SMT2: in questo modo i job dovrebbero andare a oltre il doppio della velocità vista su HP-UX, e durante il giorno, AIX sarà in grado di assegnare tutta la potenza di calcolo ai vari utenti OLTP.

Beh, alla prova dei fatti, non è andata proprio come da aspettative: durante la prima esecuzione l’MRP ha girato nello stesso tempo in SMT2 e in SMT8. Vediamo come andrà nei prossimi giorni.

Lezioni imparate:

  1. evitare SQL*Net come la morte;
  2. evitare TCP/IP in locale;
  3. il processore IBM POWER8 a 3HGz del 2014 in SMT4 non ha una potenza di calcolo maggiore dell’Intel Itanium 2 a 1,66GHz del 2007 se misurata per singola CPU logica;
  4. le licenze oracle costano un botto;
  5. lo unix di IBM — AIX — è il peggiore di tutti e non ha neppure la possibilità di assegnare i limiti per gruppo.

Un commento su “Metti che prendi un IBM Power8 per risolvere tutti i tuoi problemi”

I commenti sono chiusi.