Stai visualizzando una vecchia versione di questo article. Visualizza la versione più recente.

Ho appena effettuato il backport delle patch per le prestazioni su Windows da 5.5 a MariaDB 5.3. In MariaDB ce ne sono più che in MySQL 5.5, ma su questo punto tornerò più tardi.

Prima di tutto, ritengo che i miglioramenti alle performance su Windows in 5.5 non sono mai stati descritti adeguatamente, quindi ecco un riassunto. Per coloro che hanno familiarità con la programmazione su Windows, il codice di MySQL aveva dei problemi di prestazioni. Ne ho risolti alcuni quando lavoravo a MySQL/Sun. Il benchmark dei risultati mostra una curva interessante: si veda il post nel blog di Calvin.

Se i grafi di questo blog vi sono familiari, è perché sono stati spesso usati dal marketing di Oracle come prova dell'influenza positiva di "big O" su MySQL :)

Ci sono state tre patch per le performance su Windows. Farò anche qualche commento sulla storia dei bug.

  • Bug#24509. Il fix ha eliminato il limite di 2048 file aperti per MyISAM e come gradito effetto collaterale permette di impostare una cache per le tabelle molto più grande. All'avvio di mysqld legge il massimo di file che possono essere aperti, e corregge il valore della cache delle tabelle, se max_open_files è basso o se max_connection è alto. Questo è ciò che è accaduto anche durante i benchmark. Se si osserva il grafo dei benchmark a sola lettura nel post di Calvin sopracitato, si nota un angolo intorno ai 64 utenti concorrenti. Nessuna meraviglia: il server mysql ha ricalcolato le dimensioni della cache delle tabelle e l'ha impostata al minimo assoluto, cioè 64.

Con il fix è stata creata una sorta di libreria C runtime sopra il puro Win32, che è in grado di gestire più di 2048 file aperti (16K è il default). Anche altri aspetti sono stati migliorati rispetto al runtime di Microsoft C, per esempio non ci sono lock e vi è un'implementazione accittabile di pread()/pwrite(). Il vantaggio principale, come ho detto, è il poter disporre di una cache delle tabelle più grandi - riscrivere il runtime C è probabilmente una strage, ma non sono riuscito a trovare niente di meglio.

  • Bug#52102. Con questo bug sono stati risolti molti punti discutibili di InnoDB, probabilmente scritti ai tempi di NT 3.1.

Prima di tutto occorre capire come viene acquisita la struttura "mutex" da InnoDB. I dettagli sono complessi, il mutex è una struttura complessa che contiene un vero mutex del sistema operativo (che sotto Windows si chiama CRITICAL_SECTION) più un evento InnoDB (che sotto Windows si chiama evento). Ci sono stati un paio di cambiamenti nell'implementazione - il mutex può essere una variabile atomica (chiamata così per i miei amici Unix), sotto Unix un evento è rappresentato come variabile di condizione.

L'acquisizione viene effettuata in due passi - prima un trylock su un mutex di sistema, possibilmente più volte in un ciclo se non ha successo; l'evento viene riservato in una tabella globale di eventi chiamata "sync array"; l'evento entra in stato di attesa. Lo sblocco del mutex sveglia quelli che sono in attesa, se ce ne sono. Non chiedetemi perché l'implementazione sia così complicata: è così :) Forse, questa struttura aiuta a trovare i deadlock.

Variazione di questa implementazione - invece di fare un trylock su mutex, ora c'è un'istruzione compare_exchange sulle variabili atomiche.

Tornando a Windows, l'implementazione sopra spiegata espone un paio di interessanti bug che si compensano a vicenda.

  1. First, I fixed os_mutex_trylock() to be what it really means . The implementation was EnterCriticalSection, which is "try very hard", and actually acquire the lock. A more conscious trylock would be TryEnterCriticalSection. When I fixed that, contrary to my expectation, this made mysqld really slow. When trylock() failed, innodb started to enter code paths it has never seen before. for example, reserving space in the mentioned "sync array". Access to sync array is protected by so-called "slow lock" and this showed up very often in the profiler. The next step was fixing the "slow lock"
  2. "slow Innodb mutex" was implemented as kernel object aka Windows mutex (for my Unix friends this is sort of SysV semaphore). It can be used to synchronize processes but is an absolute overkill for synchronization of threads inside the same process. It was a "really slow mutex". Changing this to CRITICAL_SECTION made it faster however...
  3. When all of the above was fixed, found out that Windows events (mentioned events) did not really scale well in many-threads scenarios. On newer Windows (Vista+), there is a CONDITION_VARIABLE that is documented to scale better, and measuring also showed that it scaled really well. So I used condition variables when possible, which is ironic, because InnoDB events were really modeled after Windows events.
  4. Reenabled implementation of fast mutexes as atomic variables. Prior to the patch, precompiler flags to enable atomics were commented out with "Windows atomics do not work well" in CMakeLists.txt. Great comment, given that unlike software developers, atomic instructions have no preferences for the OSes they are being used on :)

So, the story about "atomics did not work well on Windows" was a cumulative effect of different things.

Prior to that patch . Once atomics were enabled, implementation of fast mutexes did not use CRITICAL_SECTION, but compare_exchange instruction. Ingenious "trylock_veryhard" as we have seen at the step 1. above is not used anymore, instead it is a quite correct "try" lock . Once try_lock() began to fail with many concurrent threads, overhead of sync array guard implemented as Windows kernel object that we have seen in 2. became apparent, and less-then inefficient Windows events mentioned in 3. finished that picture.

This patch was merely to compensate for negative effects of the 5.5 metadata lock on MyISAM bechmarks, and fix was using native Vista performance primitives. The patch per se is not interesting, and repeats a lot of what was done for Innodb. What was great, was a discussion prior to the patch between myself, Davi, Dmitry on different implementations of reader writer locks, including 2 homebacked ones, and one by Vance Morrison.

Without doubt, the discussions around that was a highlight in my very short stint at Oracle. Also, if you want to get a MySQL-classic-style code review with 17 things to fix, of which at least 10 would be marked with "Coding Style" (yes, both words capitalized) , try to get Dmitry Lenev as a reviewer, he's great - this is the proof http://lists.mysql.org/commits/118295 Anyway, the patch improves MyISAM throughput by 10-20% , which I think is quite ok. Somehow those percents were subsequently eaten by MDL though :)

Notes

Taken from a note on Facebook: https://www.facebook.com/note.php?note_id=238505812835782 by Vladislav Vaintroub.

Commenti

Sto caricando i commenti......