De finale
Wat begon rond
en
leverde een performance trouble shooting guide op van mij voor @jacovn en het nodige test werk door ons samen.
De afgelopen dagen hebben @jacovn en ik zijn probleem opgelost en echt wirespeed overdracht snelheden behaald.
Er waren grof gezegd twee problemen:
-1- Er moest 18TB over gezet worden van de ene naar de andere server
-2- De overdracht snelheid van diverse mechanismen liet te wensen over
Bonus punten vielen te verdienen met
-iperf op wirespeed te krijgen
Als eerste wil ik @jacovn complimenteren met z'n goede hardware en doorzettings vermogen.
Even iets over de systemen:
De data moest van
zfsguru3 naar
zfsguru1
Beide systemen zijn via gigabit en 10gigabit ethernet met elkaar verbonden via een D-Link DGS-1510-28X. Gigabit en 10gigabit zijn gescheiden via vlan en elk in een verschillend ip subnet.
@jacovn haalde via NFS zo'n 140MB/sec voor een enkele stream en SMB 100MB/sec, zie
metingen.
Dat was niet echt top. In reactie op @jacovn zn teleurstellende resultaten had ik deze
troubleshooting guide voor hem opgesteld.
Als eerste heeft @jacovn alles op standaard gezet door een machine opnieuw te installeren en de settings voorzover nodig over te nemen op de andere. Daarnaast zijn alle powersafe features als frequency scaling en disk power management uitgezet.
Voor de rest was er helemaal niets getuned of getweaked, schoon out of the box.
Als eerste had ik voorgesteld om via iperf (2.0.5) te kijken wat de maximum tcp snelheid was. Dit bleek in eerste instantie zo'n 4500 mbit/sec te zijn. Nog lang niet 10gbit.
Maar ipv dat we eerst dat verder gingen uitzoeken was @jacovn lekker door gegaan met de volgende stappen in de guide.
Uiteindelijk moest de data over van de ene naar de andere zpool. Aangezien dit het grote ZFS topic is gaan we dat niet doen via, NFS, rsync, scp of wat dan ook. Wij gebruiken natuurlijk zfs send en receive.
Aangezien zfs send en receive zelf alleen maar naar stdout schrijven en lezen van stdin heb je een hulp programma nodig om het netwerk transport te verzorgen. Veel gebruikte tools zijn ssh en netcat maar mbuffer is mijn grote favoriet.
Omdat er tijdens de overdracht tal van factoren een rol spelen in de totale overdracht duur en daarmee de gemiddelde snelheid heb ik alles grotendeels onafhankelijk getest om te laten zien waar bij @jacovn de bottleneck zat. Ook hoop ik dat het hierna duidelijker is dat dit soort problemen maatwerk zijn.
We wisten dat iperf niet echt de maximale 10GBit wist te behalen. Kon mbuffer dat wel?
Als eerste zetten we een ontvanger (zfsguru1) op die alles naar /dev/null weggooide. Daarna een zender (zfsguru3) die van /dev/zero zo snel mogelijk naar mbuffer schrijft en diezelfde mbuffer die dat zo snel mogelijk naar de ontvanger stuurt
code:
1
2
3
4
5
6
7
8
9
10
| zfsguru1# mbuffer -4 -s 128k -m 1G -I 5001 > /dev/null
in @ 1122 MiB/s, out @ 1122 MiB/s, 683 GiB total, buffer 0% full
summary: 684 GiByte in 10min 27.7sec - average of 1115 MiB/s
zfsguru3# dd if=/dev/zero bs=1M count=700000 | mbuffer -4 -s 128k -m 1G -O 192.168.3.151:5001
in @ 1122 MiB/s, out @ 1122 MiB/s, 682 GiB total, buffer 100% full700000+0 records in
700000+0 records out
734003200000 bytes transferred in 626.935080 secs (1170780234 bytes/sec)
in @ 0.0 KiB/s, out @ 1122 MiB/s, 683 GiB total, buffer 34% full
summary: 684 GiByte in 10min 27.5sec - average of 1115 MiB/s |
WTF? dat is 935GBit/sec of 1169MB/sec aan data (overhead van framing en tcp/ip komen er nog nog bij) zomaar out-of-the-box. Niks getweak aan tcp buffers, window sizes en wat voor andere setting waarvan niemand weet waar ze voor dienen.
Eerste conclusie met mbuffer werd het netwerk maximaal belast.
Vervolgens het overzetten van de data met zfs send en receive.
code:
1
2
3
4
5
6
7
8
| zfsguru1# mbuffer -4 -s 128k -m 1G -I 5001 | zfs recv -vFd pool 1/share
receiving full stream of tank5/share@2015-04-09 into pool1/share/share@2015-04-0 9
in @ 0.0 KiB/s, out @ 0.0 KiB/s, 18.5 TiB total, buffer 0% full
received 18.5TB stream in 23456 seconds (829MB/sec)
zfsguru3# zfs send -R tank5/share@2015-04-09 | mbuffer -4 -s 12 8k -m 1G -O 192.168.3.151:5001
in @ 0.0 KiB/s, out @ 617 MiB/s, 18.5 TiB total, buffer 7% fulll
summary: 18.5 TiByte in 6h 30min 49.7sec - average of 829 MiB/s |
829 MiB/sec is niet verkeerd maar is ook niet wat we eerder hadden gemeten (1115MiB/sec) zonder zfs send.
Waar zat dit verschil in? Was zfs send de beperkende factor? Of kon zfs receive het niet zo snel weg schrijven?
Tijdens de overdracht had @jacovn zo af en toe wat buffer underrun gezien op de zender.
De enige manier om deze hypothese te testen was zfs send naar /dev/null te sturen en kijken hoelang dat duurde.
code:
1
2
3
4
| zfsguru3# zfs send -R tank5/share@2015-04-09 | dd bs=1M of=/dev/null
0+465976080 records in
19445956+1 records out
20390563309236 bytes transferred in 22908.047300 secs (890104820 bytes/sec) |
Dat is dan 848 MiB/sec. Dit is sneller (6h 21min 48sec) dan over het netwerk (6h 30min 49.7sec). Hoe kan dit? Het verschil tussen de pieken en dalen in snelheid van zfs send is groter dan mbuffer kan vereffenen. Dus zfs send kan de data zo af en toe niet snel genoeg lezen van het enkele RAIDZ2 vdev in de pool.
Om de jumbo frame discussie ook maar te beslechten hebben we de synthetische test herhaald maar nu met jumbo frame support.
ix0 van MTU 1500 naar 9000 gezet
wederom de mbuffer icm dd test
code:
1
2
3
4
5
6
7
8
9
10
| zfsguru1# mbuffer -4 -s 128k -m 1G -I 192.168.3.153:5002 > /dev/null
in @ 1180 MiB/s, out @ 1180 MiB/s, 683 GiB total, buffer 0% full
summary: 684 GiByte in 9min 53.9sec - average of 1179 MiB/s
zfsguru3# dd if=/dev/zero bs=1M count=700000 | mbuffer -4 -s 128k -m 1G -O 192.168.3.151:5002
in @ 1180 MiB/s, out @ 1180 MiB/s, 682 GiB total, buffer 100% fulle700000+0 records in
700000+0 records out
734003200000 bytes transferred in 593.192158 secs (1237378462 bytes/sec)
in @ 0.0 KiB/s, out @ 1180 MiB/s, 683 GiB total, buffer 21% full
summary: 684 GiByte in 9min 53.8sec - average of 1179 MiB/s |
Ter vergelijking bij een MTU van 1500 duurde het 10min 27.5sec met een gemiddelde van 1115 MiB/sec
en nu met een MTU van 9000 duurde het 9min 53.9sec met een gemiddelde van 1179 MiB/sec
Dat is zo'n 5% tijd winst.
Waren er nog andere verschillen? Ja alleen de cpu load op de ontvanger zakte van zo'n 17% naar 10% de interupt tijd bleef gelijk en op de verzender bleef alles min of meer hetzelfde. Waarom niet een groter verschil? Omdat het hier om goede moderne netwerk kaarten gaat, Intel X520-DA2, met allerlei offload features. Bij oudere of mindere kaarten is dit verschil groter.
Hebben jumbo frames zin?
Hier misschien niet zo veel. Toch in het algemeen is er veel voor te zeggen. Je moet de zaken wel goed in richten, zet het altijd in een vlan, plaats het in een eigen non routable subnet. Mijn ervaring is dat jumbo frames voor storage toepassing altijd pure winst zijn. Vooral bij vSphere toepassingen is het net dat beetje extra. Ik zou het niet zomaar inzetten tussen je pc en je nas.
Om het verschil tussen
MTU 1500 en
MTU 9000 te illustreren heeft @jacovn wat spectaculaire beelden op youtube gezet.
Let op de load links boven!
Ook nog een
filmpje van de zfs send en receive van 18TB waarbij het grillige karakter van zfs send te zijn is. Ook is nu goed te zien dat het lezen van disk en versturen en weer wegschrijven naar disk op maximale snelheid wel resources kost. De Xeon E3-1265LV2 @2.5 GHz was op de ontvanger voor zo'n 70% belast met alleen de stream weer weg te schrijven. Er is daar weinig ruimte om nog een beetje transcoding te doen.
De volgende conclusies kunnen worden getrokken
-de totale duur van zfs send hangt af van de onderliggende data. Veel kleine files kosten meer tijd dan een paar grote binaries.
-mbuffer is een handige tool om pieken en dalen van zfs send te vereffenen. De grote van de buffer hangt mede af van het verschil tussen pieken en dalen. De buffer moet zoveel data bevatten dat voordat de buffer leeg is zfs send weer op wirespeed of sneller data aanlevert.
-de grote buffer aan de ontvangende kan had hier nauwelijks effect. Toch kan het handig zijn. Bijvoorbeeld als de zpool van de ontvanger belast is. Dan kan de zpool misschien niet altijd alles op tijd wegschrijven dan kan de buffer handig zijn.
-Steekproeven hebben alleen zin als het om een representatieve sample gaat. @jacovn had op een gegeven moment wat directories naar een anders ZFS filesystem gecopieerd. En gemeten hoe lang dat duurde met zfs send. Toen bleek die data met 1.1GB/sec te kunnen worden gelezen, terwijl ALLE data lang niet zo snel kon worden gelezen. Als je het echt wilt weten meet dan over de hele dataset.
-Ook zie je hier dat de organisatie van de vdevs van invloed is op de (lees) prestaties. De verzender las vanaf een pool met 10x een Hitachi 7K4000 in een enkele RAIDZ2 vdev. Worst case read performance is dat van een enkele disk bij RAIDZx en dat is wat er ook enkele malen gebeurde.
Samenvatting
- Van 140MB/sec met NFS naar 829MiB/sec via zfs en mbuffer. Probleem opgelost. Wil je nog sneller? Splits de pool op in twee vdevs.
- ZFSGuru gebaseerd op FreeBSD 10.0-STABLE is out-of-the-box in staat om 10GBit ethernet zonder enige tweaks helemaal vol te schrijven. Hulde aan FreeBSD.
- Ga niet te snel allemaal tweaks doen die je eigenlijk niet snapt. Bedenk wat testen om er achter te komen waar de bottleneck zit. Misschien kom je er achter dat je helemaal niet hoeft te tweaken want het gaat niet sneller om welke reden dan ook.
- Ik denk niet dat welke applicatie of protocol zo snel de data kan over zetten als zfs send / receive icm mbuffer. Daarnaast verlies je bij iedere andere tool je zfs metadata en eventuele snapshots.
- Als ik een ranking zou moeten maken van file sharing protocollen van snel naar langzaam voor een unix systeem dan dat er als volgt uit zien:
- FTP, simpel snel en sommige clients kunnen meerdere streams tegelijk versturen
- NFS, simpel om op te zetten lastig om de performance van mbuffer te evenaren
- SMB en dan met name SMB2. Soms makkelijk op te zetten soms moeilijk als het met de hand moet. Ook hier zal niet zonder meer (lees bij lange na niet) de performance van mbuffer worden evenaard. SMB3 is een ander verhaal maar dat is op unix nog niet echt mainstream.
Optioneel heb je nog tools nodig om het copieren parallel uit te voeren. - Dan zit je met het probleem van crash recovery en gebrek aan data integriteit.
- En voordat iemand rsync noemt... diegene heeft nog nooit rsync gebruikt. RSync werkt prima als de data is over gezet niet om te copieren.
- Deze zelfde transfer kan je op gigabit wel met een kleine pentium afhandelen. Voor 10GBit heb je een zwaardere CPU nodig.
Slotopmerkingen
In het begin had ik voorgesteld om met iperf, wat een zeer geaccepteerde tool is, een baseline van het netwerk vast te stellen. Bij de standaard settings leverde dit over een minuut gemeten zo'n 7700MBit/sec op. Na enkele pogingen om dit te verbeteren ben ik hier snel mee gestopt. Mede omdat mbuffer wel volle snelheid wist te behalen. Ik heb later nog een keer getracht dit te verbeteren maar kwam niet hoger dan 7700MBit. Ik zal nog eens kijken of ik wirespeed op FreeBSD kan halen met iperf. Het is zonde om je tijd in iperf te stoppen ipv zfs send en receive.
Het was erg leuk om dit op te schrijven en de samenwerking met @jacovn was erg prettig.
Als lezers nog opmerkingen, vragen of nieuwe onderzoeks voorstellen dan hoor ik dat graag.