Hallo Gea,
ich sichere ein ZFS-Dataset mit ESXi-VMs (NFS-Datastore, VMDKs) per `zfs send | ssh | zfs recv`
von einem OmniOS-Filer auf einen zweiten OmniOS-Server. Der volle Erstlauf ist schnell, jeder
inkrementelle Lauf danach ist dagegen um ein Vielfaches langsamer — obwohl er nur einen Bruchteil
der Daten enthält. Ich würde gern verstehen, ob das erwartetes ZFS-Verhalten ist, bevor ich an
Kernel-Tunables drehe.
**Umgebung**
- Quelle: OmniOS r151054 (`omnios-r151054-a81cbdaf88`), Pool `Micron1` = eine SATA-SSD (single
vdev, ashift 12), Dataset `recordsize=128K`, `compression=lz4`, `sync=standard`, `atime=off`.
Inhalt: acht VMs als NFS-Datastore für ESXi, 12,7 GB belegt (thin VMDKs).
- Ziel: OmniOS r151058 (`omnios-r151058-516f7694c9`), drei Pools `SAS1`–`SAS3`, jeweils ein
Mirror aus zwei SAS-HDDs, Dataset gleiche Properties. `zfs_per_txg_dirty_frees_percent = 30`,
`zfs_dirty_data_max ≈ 1,6 GB`, `zfs_txg_timeout = 5` (alles Default, nichts in `/etc/system`).
- Strecke: 10 GbE, `zfs send -c -v … | ssh root@ziel "zfs recv <pool>/yummisites"`. Kein
mbuffer (gemessen: bringt hier nichts, Deckel ist die Schreibrate des Mirrors, ~115 MB/s).
- Snapshots werden von Hand bei ausgeschalteten VMs angelegt (`zfs snapshot -r`).
**Messung**
Voller Erstlauf (`zfs send -c snap@A | zfs recv -F`): 12,7 GB in ~90 s je Pool — passt zu den
115 MB/s der Platten.
Inkrementeller Lauf danach (`zfs send -c -i A B`), Stream laut `zfs send -nv`: **69,9 MB**.
`zstreamdump` des Streams:
```
Total DRR_OBJECT records = 198
Total DRR_FREEOBJECTS records = 58
Total DRR_WRITE records = 4188
Total DRR_FREE records = 1181
Total records = 5627
Total write size = 69792256
Total stream length = 71582416
```
Zwischen A und B wurden die VMs heruntergefahren; die 1181 FREE-Records sind vermutlich die
Bereiche, die die Gäste beim Shutdown in ihren VMDKs freigegeben haben (Swap, Logs, Truncate).
Derselbe Stream, aber ohne Empfang (`zfs send -c -i A B | ssh ziel "cat > /dev/null"`): **1 s**.
Mit `zfs recv`: **10 min 44 s** je Pool. `zpool history -il` auf dem Ziel:
```
08:43:47 [txg:657773] receive SAS3/SAS3/yummisites/%recv
08:54:31 [txg:659374] finish receiving SAS3/SAS3/yummisites/%recv snap=B
```
Also **1601 Transaktionsgruppen in 644 s** (2,5 txg/s) für 70 MB — Netz und Send sind
nachweislich nicht der Engpass, `zpool status` sauber, kein Scrub/Resilver, keine Plattenfehler,
Load 0,1. Ein zweiter Inkrementallauf ohne FREE-Records (nur Writes) läuft in Sekunden.
**Meine Vermutung**
Der Empfänger verarbeitet die FREE-Records über `dmu_free_long_range()`, und die Drossel
`zfs_per_txg_dirty_frees_percent` erzwingt bei grossen freigegebenen *Adressbereichen* (thin
VMDKs: wenig belegt, aber grosse Ranges) laufend `txg_wait_synced()` — daher die vielen kleinen
txgs und die Wartezeit auf die HDDs, obwohl kaum Daten geschrieben werden. Beim vollen Send gibt
es keine FREE-Records, deshalb ist er schnell.
**Fragen**
1. Ist das so erwartet, oder übersehe ich etwas (Property am Dataset, Stream-Option)?
2. Ist `zfs_per_txg_dirty_frees_percent` hier die richtige Stellschraube, und mit welchem Wert
(höher, oder 0 = Drossel aus) — oder rät man davon auf einem Backup-Ziel eher ab?
3. Gibt es einen sinnvolleren Weg, VM-Datastores mit vielen Freigaben inkrementell zu
replizieren (z. B. `zfs send` ohne `-c`, anderes `recordsize` am Ziel, `logbias=throughput`)?
Für ein Backup-Ziel, das ohnehin nur nachts läuft, ist das kein Drama — ich möchte nur wissen,
ob ich einem Bug hinterherlaufe oder einem Designmerkmal.