Oke nou als je het tot zover volgt dan ben je er al bijna! Zelf testen vervolgens en je snapt hoe I/O performance écht werkt; alles is gekoppeld aan elkaar: latency (ms), IOps en throughput (MB/s). Het valt me wel op dat ik dit zelf moest uitvinden en er relatief maar weinig over I/O performance te lezen is op het web wat echt verhelderd, dus laat ik je proberen te leren wat ik zelf geleerd heb.
De kern van je verhaal is: als je een kleine stripesize kiest en je gaat een groot bestand lezen of schrijven, heb je veel meer IOps nodig om dezelfde throughput te bereiken, dat klopt helemaal!
Command overhead
Echter, meer IOps om dezelfde throughput te bereiken betekent nog niet automatisch langzamer. Er is wel iets meer overhead en als je lager gaat dan 32KiB stripesize dan zul je hier wel last van krijgen. Overigens vooral door je CPU; Windows is bijvoorbeeld single-threaded zoals ik heb gemerkt; als je kleine request sizes heel veel IOps gaat doen zoals met ATTO, dan zul je zien dat je CPU bottlenecked wordt op maar één core. Als je een quadcore met hyperthreading hebt (8 virtuele cores) wordt dat lekker gemaskeerd door slechts 12.5% cpu belasting; niets aan de hand toch, ligt aan de schijf! Maar dat is dus niet zo; de schijf kan echt veel IOps aan voor sequential I/O. Dat kun je testen met dd in Linux. Mijn tests waren trouwens op FreeBSD, wat een best geavanceerd I/O framework heeft dat
GEOM heet. Met een simpel 'gstat' commando kun je de I/O volgen die je met 'dd' veroorzaakt. Probeer een kleine blocksize (bs=512) en een grote (bs=128k) en zie hoe de IOps en throughput en latency van elkaar verschillen. Dit heeft mij enorm veel geleerd door echt te zien wat ik doe met benchmarks, in plaats van gewoon een getal krijgen als resultaat en het daarmee maar moeten doen; geen verklaring over het
waarom achter dat getal.
Read ahead
Het punt van een kleine stripesize, is dat je ook met weinig I/O al meerdere disks aan het werk zet. Met een stripesize van 32KiB en 4 disks, betekent dat er maar één request van 128KiB nodig is om alle requests aan het werk te houden. Oftewel aan queue depth = 1 heb je genoeg. Met een stripesize van 1 Megabyte moet je in totaal 4 megabyte vooruit lezen om alle schijven 'bezig te houden'; dat zul je sowieso moeten tweaken anders krijg je heel trage throughput omdat er maar een beperkt aantal schijven op enig moment van werk voorzien kan worden. Stel je past 128KiB readahead toe waar 4MiB nodig is, dan krijg je niet veel meer doorvoerperformance (throughput) dan een enkele disk.
Per saldo
Het positieve effect van laatstgenoemde, is veel sterker dan het negatieve effect van eerstgenoemde, waardoor per saldo dus zo is dat kleine stripes goed/beter zijn voor sequential I/O en grote stripesize noodzakelijk is voor maximale random IOps waarbij het 99,999% op de seektime aankomt en je dus nooit wilt dat twee schijven aan één request werken zodat ze beide naar een enkele I/O moeten seeken. Je wilt dat alle schijven in de stripe naar een andere random I/O request seeken zodat ze elk maar één seek per I/O hoeven uit te voeren. In dat geval heb je dus vier hardeschijven die kunnen seeken naar individuele locaties. De enige 'maar' in dat verhaal is dat door de striping het soms zal gebeuren dat de ene disk meer requests krijgt dan de ander, en dus dat het niet perfect verdeeld wordt over alle schijven.
Random & Sequential I/O
Random I/O wil zeggen dat er geen 'contiguous' requests zijn, requests die netjes op elkaar aansluiten. Bij Sequential I/O zal de HDD blokken opgevraagd krijgen die netjes elkaar opvolgen. De HDD herkent dit patroon en past intern read-ahead toe en writes worden altijd al gebuffered. Bij Random I/O kan dat niet, random I/O wil dus zeggen een I/O patroon wat voor de HDD niet te voorspellen valt.
Stripesize
Stripesize wordt vaak verkeerd begrepen. Het is niets anders dan 'interleaving'; het in elkaar vlechten van de schijven in een soort round-robin patroon. Als je dus minder schrijft/leest dan de stripesize, zet je één disk aan het werk, als je méér schrijft dan zet je meerdere schijven aan het werk.
Offset
Maar nu nog wat ingewikkelder, offset/alignment! Dat wordt vaak helemaal niks over gezegd. Je HDD en RAID array bestaat uit sectoren; 512-bytes bijna altijd. Nu gaan veel benchmarks die "Random I/O" doen er van uit dat je altijd een alignment van 4 kilobytes aanhoudt. Dus zij doen Random I/O zoiets als 8 KiB - 12KiB lezen, waarbij 8 dus keurig begint op een 4KiB-alignment boundary. Wat ze niet doen is 7.5 - 11.5KiB; dat is pas ECHT random I/O; met 512-byte alignment. In IOmeter kun je dit instellen en een rits benchmarks onder Linux vast ook; even zoeken in de manpage!
Kan nog veel meer vertellen, maarehh; misschien leuk om een apart topic te maken? Zoals 'de theorie achter RAID' ofzoiets. Wil er best wat meer over vertellen; te meer omdat ik niet zo gauw URLs kan geven waar dit alles wordt uitgelegd.