ZFS auf Linux/ Fragmentierung

FragmentierungBearbeiten

  1. Was ist Fragmentierung ?
  2. Wie kann ich sie messen ?
  3. Wie kann ich sie erzeugen ?
  4. Wie bekomme ich das wieder weg ?

AllgemeinesBearbeiten

Fragmentierung bezeichnet die Tatsache, dass ein Datenstrom nicht auf hintereinanderfolgende Blöcke geschrieben wird. Fragmentierung verlangsamt Lesen und Schreiben, da mehr Bewegungen der Plattenköpfe notwendig sind.

ZFS speichert die Daten in der Copy-on-write (COW) Technik. Wenn also ein Datenblock überschrieben werden soll, wird dieser zuerst kopiert (an eine neue Stelle auf der Platte), dann modifiziert und schließlich der alte Block verworfen. Dies führt dazu, dass einst zusammenhängende Daten nach häufiger Überarbeitung fragmentiert vorliegen. Das Positive an COW: Die Daten sind immer konsistent (nie fsck), ein Snapshot kostet keine Zeit.

Fragmentierung macht vor allem volle Pools langsam.


Messen der FragmentierungBearbeiten

FRAGBearbeiten

Der Befehl "zpool list" zeigt eine Spalte "FRAG":

user> sudo zpool list zpooltest
NAME        SIZE  ALLOC   FREE  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zpooltest  1.50G  1.45G  48.5M         -    80%    96%  1.00x  ONLINE  -

FRAG:

  • FRAG ist ein Maß dafür, wie fragmentiert der freie Platz in einem zpool ist, wie schwer ZFS arbeiten muss, um neue Daten in den Pool zu schreiben.
  • Wenige Prozente bedeuten, dass der freie Platz als langes, zusammenhängedes Segment beschrieben werden kann und ZFS wenig Mühe hat damit. Und umgekehrt.
  • FRAG sagt nichts darüber aus, wie stark fragmentiert die bereits geschriebenen Daten im Pool sind.
  • FRAG macht keine Aussage darüber, wie gleichmäßig die Daten über die Platten des Pools verteilt sind.
  • Ein Pool mit "ashift=12" kann zu maximal 95% FRAG aufweisen.


zdbBearbeiten

zdb kann die exakte Positon und Größe aller Blocks im Dataset in sehr unübersichtlicher Ausführlichkeit auflisten. gawk kondensiert diese lange Liste zu einem 4-Zeiler.

user> sudo zdb -ddddd zpooltest | gawk --non-decimal-data -f /tmp/fragments.awk
There are 54 files.
There are 47 blocks and 3 fragment blocks.
There are 2 fragmented blocks (66.67%).
There are 1 contiguous blocks (33.33%).
Parameter Erklärung
-d (display) zeigt Infos über ein Dataset. Mehr d's, mehr Infos

Das gawk-Programm in /tmp/fragments.awk:

mehr/weniger
/Indirect blocks/{
file_number++; 
next_block = 0; 
}
/L0/{
split($3,fields,":");
this_block = ("0x"fields[2])+0;
this_block_size = ("0x"fields[3])+0;
total_blocks++;
if( next_block != 0 ) {
if( next_block == this_block )
not_fragmented++;
else
fragmented++;
}
next_block =  this_block + this_block_size;
}
END{ 
printf("There are %d files.\n", file_number ); 
total_fragment_blocks = fragmented + not_fragmented;
printf("There are %d blocks and %d fragment blocks.\n", total_blocks, total_fragment_blocks ); 
printf("There are %d fragmented blocks (%2.2f%%).\n", fragmented, fragmented*100.0/total_fragment_blocks ); 
printf("There are %d contiguous blocks (%2.2f%%).\n", not_fragmented, not_fragmented*100.0/total_fragment_blocks ); 
}


FragmentierenBearbeiten

Wenn man viele Files verändert, indem man (im folgenden 8) Zeilen einfügt, vergrößert sich gemäß der obigen Erklärung die Fragmentierung. Die folgenden Zeilen machen:

  1. Kernelquellen werden heruntergeladen
  2. und ausgepackt
  3. Der einzufügende File wird erzeugt.
  4. In alle Files der Kernelquellen, die find im aktuellen Unterverzeichnis ./linux-4.5.1/ findet, wird nach der 11. Zeile (11r) der Inhalt des Files /tmp/insertion.txt von sed eingeschoben.
user> wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.5.1.tar.xz /zpooltest
user> tar -xvJf linux-4.5.1.tar.xz
user> echo -e "  This\n  text\n  will\n  be\n  inserted\n  in\n  every\n  file."  > /tmp/insertion.txt
user> time find ./linux-4.5.1/ -type f -exec sed -i '11r /tmp/insertion.txt'  {} \;


De-FragmentierenBearbeiten

ZFS fehlt, wie Linux, ein Tool zur Defragmentierung, weil es normalerweise nicht nötig ist, da beide sich Mühe geben, selbige zu vermeiden.

Will man ein Dataset defragmentiern, dann muss man es umkopieren.

To-Do:

Dateiweise umkopieren testen: find exec mit cp file-a tmp && mv tmp file-a



Siehe auchBearbeiten