programmatūra · 5 min · 10.09.2026

Btrfs zstd lasīšanā katrs baits tika rakstīts divreiz: 56 rindas dod 7,8 %

Usama Arif ielāps, kas 7. septembrī nonāca Btrfs zarā for-next, izmet vienu atmiņas kopēšanu no zstd atspiešanas ceļa. Līdz šim katrs baits, ko zstd izsniedza Btrfs lasīšanas ceļam, tika ierakstīts atmiņā divas reizes.

Izmaiņa ir 56 pievienotas rindas pret 13 izņemtām vienā failā fs/btrfs/zstd.c. Secīgā lasīšana ar 4 KiB sektora izmēru pēc ielāpa aizņem 8,004 milisekundes iepriekšējo 8,678 vietā. Tas ir par 7,8 % mazāk.

Kur radās dubultā rakstīšana

Funkcija zstd_decompress_bio() zstd bibliotēkai padeva melnraksta buferi sektora izmērā. Pēc tam btrfs_decompress_buf2page() no šī bufera kopēja uz galamērķa folio struktūrām to daļu, kas pārklājas ar lasīšanas bio. Dati vispirms nokļuva buferī, tad otrreiz lapu kešatmiņā.

Atspiešanas ceļš strādā pie katra lasījuma, kas datus kešatmiņā neatrod. Tāpēc lieka kopēšana tur maksā vairāk nekā tā pati kopēšana saspiešanas pusē. Kopēto baitu skaits sakrīt ar visu nolasīto datu apjomu.

Arifs izvēlējās izvades buferi noteikt katram straumēšanas izsaukumam atsevišķi. Jaunā funkcija zstd_map_dest() ar kmap paņem to lasīšanas bio segmentu, kas ietilpst vienā lapā. Zstd raksta tieši lapu kešatmiņā.

Melnraksta buferis palicis tikai tādai izvadei, kurai nav galamērķa: prefiksam pirms lasīšanas, kas sākas saspiesta extent vidū un ko zstd nevar izlaist, kā arī atstarpēm, kuras atstāj folio, kas jau ir lapu kešatmiņā.

Tā Arifs pats apraksta ielāpu komita ziņojumā.

Kāpēc mainīgs izvades buferis ir drošs

Btrfs lieto zstd noklusējuma režīmu ZSTD_bm_buffered. Tajā slīdošais logs dzīvo dstream iekšējā buferī, tāpēc izsaucēja dst ir tikai izvades galapunkts. Buferi starp izsaukumiem var mainīt bez sekām atspiešanas stāvoklim.

Viena vieta tomēr prasīja uzmanību. Lasīšanas bio iteratoram joprojām jāpavirzās tieši par tik baitiem, cik izsniegts, jo btrfs_decompress_bio() no tā aizpilda nulles. Agrāk tas notika btrfs_decompress_buf2page() iekšienē. Tagad kodā ir atsevišķs bio_advance() izsaukums, kas notiek tikai tai izvadei, kura sasniegusi folio.

Ir arī cena. bio_iter_iovec() atklāj ne vairāk kā vienu bāzes lapu, tāpēc tiešā izvade ir ierobežota ar lapas robežu. Ja sektora izmērs pārsniedz PAGE_SIZE, straumēšanas izsaukumu skaits var pieaugt, salīdzinot ar veco pieeju sektora izmēra gabalos.

Mērījumi

Arifs testēja divu vCPU x86-64 KVM viesī ar 4 KiB lapām un RAM disku. Fails bija 64 MiB liels, saspiests ar zstd. Katrs rezultāts ir mediāna no septiņiem lasījumiem ar tukšu kešatmiņu. Mērījumi izpildīti sešos pārmaiņus veiktos A/B pāros, katrs pāris ar savu pārstartēšanu. Pirms katra lasījuma mincore apstiprināja, ka rezidentu lapu nav. Secīgie lasījumi notika ar ieslēgtu readahead, tāpēc skaitļi rāda parastu failu lasīšanu, nevis sintētisku vienas lapas gadījumu.

  • 4 KiB sektors: 8,678 ms pret 8,004 ms, ieguvums 7,80 %
  • 16 KiB sektors: 8,216 ms pret 7,934 ms, ieguvums 3,64 %
  • 64 KiB sektors: 7,875 ms pret 7,344 ms, ieguvums 6,88 %

Nejaušai 4 KiB lasīšanai ar pread caurlaide auga no 264,33 MB/s uz 272,67 MB/s. Tie ir 3,2 %. Ielāps uzvarēja visos sešos pāros.

Zīmīgākā ir 64 KiB rinda. Tur sektors ir lielāks par lapu, tāpēc straumēšanas izsaukumu kļūst vairāk. Ieguvums tik un tā sanāk 6,88 %, kas nozīmē: izmestā kopēšana atsver papildu izsaukumus.

Kurus lietotājus tas skar

Ieguvumu redzēs tie, kas Btrfs sējumus montē ar compress=zstd. Tādu nav maz. Fedora darbvirsmas variantos anaconda instalē ar mount -o compress=zstd:1 kopš 34. laidiena, par ko raksta Fedora Magazine. Uz šādas instalācijas atspiešanas kods strādā pie gandrīz katra lasījuma no diska.

Runa ir tikai par lasīšanas ceļu. Saspiešanas puse ielāpā netiek aiztikta, tāpēc rakstīšanas ātrums paliek tāds pats.

Kas vēl gaida Linux 7.4 rindā

Tajā pašā for-next zarā nedēļas laikā ienāca vēl divi zstd labojumi. FAN YE ielāps novērš zaudētu pamodinājumu, kad process gaida darba apgabalu. Qu Wenruo pārslēdza zlib un zstd darba apgabala bufera piešķiršanu no kmalloc uz kvmalloc.

Wenruo to pamato ar eksperimentālo atbalstu blokiem, kas lielāki par lapu. Šādā konfigurācijā buferis var būt 64 KiB, bet uz sistēmām ar 4 KiB lapām kmalloc šādam apjomam prasa fiziski secīgu atmiņu. Tāpēc piešķiršana biežāk neizdodas. LZO kods kvmalloc lietoja jau agrāk.

Neviens no šiem ielāpiem vēl nav kodola galvenajā zarā. Linux 7.4 apvienošanas logs sākas oktobrī, tāpēc tas ir pirmais laidiens, kurā izmaiņu var sagaidīt. David Sterba ielāpu pārskatīja un parakstīja 7. septembrī.

Atsevišķi rindā stāv arī paša kodola zstd koda uzlabojumi, kas vēl nav nevienā zarā. Btrfs komandas ielāps no tiem nav atkarīgs. Komits for-next zarā ir e27a6e4.

Avoti

komentārisaruna

Komentāri

Šim rakstam vēl nav komentāru. Esi pirmais, kurš dalās ar savu viedokli.

Pievieno komentāru

Tavs e-pasts netiks publicēts. Obligātie lauki atzīmēti.

vēl no programmatūrasaistītie