← Tutti gli articoli

I vantaggi della PGO nei database si riducono con carichi più elevati nei test di Percona

I vantaggi della PGO nei database si riducono con carichi più elevati nei test di Percona

I miglioramenti delle prestazioni del database relazionale open source ottenuti con l'ottimizzazione guidata dal profilo si sono ridotti all'aumentare delle attività del database in competizione tra loro, secondo i test riportati da Marco Tusa di Percona. Una build addestrata su un insieme limitato di attività ha addirittura registrato prestazioni peggiori rispetto alla versione di riferimento. I risultati illustrano un limite pratico dell'ottimizzazione tramite il compilatore: rendere più veloce il codice usato di frequente non risolve necessariamente i colli di bottiglia che prevalgono in un database molto impegnato.

L'ottimizzazione guidata dal profilo (PGO) usa le misurazioni raccolte durante le esecuzioni di addestramento per orientare un compilatore, il software che trasforma il codice sorgente in programmi eseguibili. Una build strumentata registra quali funzioni e percorsi di esecuzione vengono utilizzati più spesso; una build successiva usa questi dati per stabilire le priorità di ottimizzazione. La terza puntata di Tusa sulla PGO esamina perché l'addestramento del database con sysbench-tpcc, un benchmark per l'elaborazione delle transazioni, abbia prodotto un risultato deludente e se un addestramento più ampio possa essere utile.

I miglioramenti riportati dipendono fortemente dal carico di lavoro. Nelle sue conclusioni, Tusa cita un miglioramento del 12% con una bassa concorrenza, ossia con relativamente poche attività in esecuzione contemporaneamente, ma inferiore al 2% con una contesa più elevata, quando queste attività competono per risorse condivise. In altri passaggi descrive miglioramenti inferiori al 5% e suggerisce che il beneficio aggiuntivo di una migliore copertura della concorrenza potrebbe plausibilmente essere inferiore all'1%. Quest'ultimo valore è una previsione, non una misurazione accertata separatamente. Questi numeri descrivono confronti diversi e non devono essere presentati come un unico aumento delle prestazioni valido in ogni situazione.

Perché un addestramento limitato può rallentare il database

Tusa individua tre problemi che si sommano tra loro. Primo, sysbench-tpcc mette alla prova solo una parte del programma server del database. Nella sua analisi del compilatore GCC, le funzioni per cui non sono state registrate esecuzioni diventano «fredde»: il compilatore privilegia un codice più compatto, evita l'inlining (l'inserimento del codice di una funzione direttamente nella funzione che la chiama) e lo sposta in regioni utilizzate meno frequentemente. Eppure, un database in esecuzione continua a svolgere operazioni di purge per rimuovere le versioni obsolete dei dati, flushing per scrivere sul sistema di archiviazione i dati modificati, ricalcolo delle statistiche, gestione degli errori, piani alternativi di esecuzione delle query e ripetute aperture e chiusure delle connessioni.

Queste operazioni possono quindi essere eseguite attraverso codice meno ottimizzato per la velocità. Anche il passaggio tra regioni usate frequentemente e regioni usate di rado può penalizzare la cache delle istruzioni, la memoria veloce del processore che contiene le istruzioni eseguibili. Tusa indica l'opzione partial-profile-training di GCC come protezione per evitare di penalizzare il codice non coperto dall'addestramento.

Secondo, segnala conteggi di addestramento inaffidabili con un numero di thread compreso tra 128 e 1024, cioè le unità di esecuzione parallele che svolgono le attività del database. Nella configurazione descritta, i contatori di profilo predefiniti di GCC non sono atomici: gli aggiornamenti simultanei non vengono necessariamente registrati come operazioni indivisibili. Alcuni aggiornamenti possono andare persi e i conteggi possono diventare incoerenti. Durante la compilazione con l'uso dei profili abilitato, Tusa ha riscontrato avvisi relativi a dati di profilo corrotti o incoerenti e identifica negli aggiornamenti atomici dei profili la protezione necessaria. Con 128 thread, la sua build PGO addestrata con sysbench è risultata più lenta di una build convenzionale con livello di ottimizzazione 3, che utilizza un livello elevato di ottimizzazione del compilatore.

Terzo, la misurazione modifica il comportamento misurato. Tusa descrive un rallentamento dell'esecuzione da 2 a 10 volte dovuto alla strumentazione. Questo cambia i punti in cui i thread si accumulano in presenza di contesa. I mutex e i blocchi di lettura-scrittura, meccanismi che coordinano l'accesso ai dati condivisi, possono trascorrere molto tempo in cicli di attesa attiva che verificano ripetutamente se l'accesso sia disponibile. I loro enormi conteggi di esecuzione possono indurre il compilatore a ottimizzare l'attesa anziché il lavoro produttivo. Riorganizzare le diramazioni del codice non può eliminare la contesa sottostante sui blocchi né i ritardi nell'accesso alla memoria.

Combinare ampiezza della copertura e attività concorrenti

L'alternativa proposta da Tusa combina il database test runner (MTR), lo strumento di test del database, con un carico di lavoro sysbench a concorrenza moderata. MTR copre un'ampia gamma di funzionalità: interpretazione delle query, selezione dei piani di esecuzione, modifica delle strutture del database, replica (copia delle modifiche tra server di database) e gestione degli errori. Tusa descrive però i suoi carichi di lavoro come basati quasi interamente su singole connessioni, lasciando poco rappresentati importanti percorsi di esecuzione concorrente.

Questi percorsi comprendono i latch soggetti a contesa, meccanismi leggeri di coordinamento; il controllo della concorrenza multiversione (MVCC), che determina quali versioni dei dati una transazione possa vedere mentre altre scrivono; le code di attesa dei blocchi; e il group commit, che raggruppa le conferme delle transazioni attraverso il redo log usato per il ripristino. Tusa propone di usare approssimativamente da 4 a 64 thread sysbench per esercitare questi percorsi senza le forti distorsioni di una concorrenza molto elevata. Assegnare loro conteggi diversi da zero aiuta a impedire che il compilatore li classifichi come inutilizzati.

La distinzione tra i compilatori è importante. Tusa spiega che il runtime di GCC può accumulare i conteggi quando esecuzioni di addestramento successive usano lo stesso eseguibile strumentato e la stessa directory dei profili, aggiungendo dati ai file esistenti alla chiusura del programma. Tuttavia, i comandi di compilazione pubblicati usano Clang 20, non GCC. La procedura mostrata unisce esplicitamente i profili grezzi con la versione 20 dello strumento LLVM per i dati di profilo, in modalità di unione sparsa, nel file dei dati di profilo del database situato nella directory dei profili dell'albero dei sorgenti, sotto la directory del software opzionale. Le protezioni di GCC non vanno confuse con opzioni mostrate come abilitate in quei comandi Clang.

Cosa comprende l'esperimento mostrato

La build strumentata usa la versione 9.7.2 del server del database, la configurazione Release, i compilatori C e C++ di Clang versione 20, il linker lld che assembla i componenti compilati del programma e la generazione dei profili abilitata. Disabilita l'ottimizzazione in fase di linking (LTO), eseguita trasversalmente sui componenti compilati durante il collegamento. L'addestramento esegue MTR con otto processi di test paralleli sulle suite di test principale, del motore di archiviazione transazionale, dell'undo del motore di archiviazione transazionale, del log binario, della replica, del performance schema e delle variabili di sistema, proseguendo anche in caso di test non superati.

La successiva esecuzione di sysbench-tpcc usa 64 thread per 600 secondi, 10 tabelle e un fattore di scala pari a 100. Seleziona i dati in modo uniforme, usa il livello di isolamento delle transazioni repeatable-read per regolare quali modifiche le transazioni possano vedere, abilita il purge e disabilita i prepared statement, richieste al database preelaborate e riutilizzabili. Le connessioni restano aperte anziché essere ristabilite ripetutamente. Queste scelte descrivono il carico di lavoro di addestramento, non una configurazione consigliata per l'ambiente di produzione.

Il riepilogo del profilo di Tusa elenca 52.403 funzioni, 619.050 blocchi di codice e un conteggio totale di 2.473.216.025.729. Il conteggio massimo per una funzione è 289.910.820.864 e il conteggio massimo per un blocco interno è 16.881.288.068. Soltanto due blocchi rappresentano il 20% dei conteggi registrati; 2.165 blocchi, pari allo 0,35%, rappresentano il 90%. Ampliando l'insieme considerato, 220.001 blocchi, pari al 35,54%, rappresentano il 99,9999%.

Tusa interpreta questo nucleo concentrato, accompagnato da un'ampia coda a bassa frequenza, come prova del contributo sia dell'attività prolungata di sysbench sia della copertura funzionale di MTR.

Disponibile anche in: EnglishDeutsch