betömörítés -- gondolkodás helyett

A múltkor megvicceltem magam, amikor a /usr-t költöztettem. (Mindent, ami alatta volt, átméreteztem; azért kellett.)

Valamiért úgy gondoltam, hogy a tar-t jó lesz lzop-vel tömöríteni. Sajnos így a kibontásnál gondok voltak: amikor már csak a /bin volt felcsatolva, akkor jöttem rá, hogy az lzop az /usr/bin-ben tanyázik. Egy LiveCD-vel megoldottam, de azért kellemetlen volt. Ezért a legközelebb nem szeretnék gondolkozni -- vagy legalább egy biztonságos alapgondolattal kezdeném.

Két végletet azonosítottam tömörített állomány létrehozásához: sebesség fontos, vagy méret fontos. Követelmény, hogy mindkettő menjen pipe-ból pipe-ba. Mértem néhány nevetségeset.

Ha a sebesség a fontos, akkor ezután a

pigz -1

parancsot fogom használni. Először is, .gz a kimenete, tehát a fentihez hasonló öntökönszúrás kockázata csökken (a gzip az égvilágon mindenhol a /bin alatt van). Másodszor, nálam (két magon) az olvasási sebessége cca. 72 MB/s, a tömörítési aránya (/usr/bin-en és /usr/lib-en tesztelve): 60% megtakarítás. Ez mind sebességben, mind megtakarításban jobb, mint az (egyszálú)

lzop -1

. Utóbbinak az olvasási sebessége cca. 50 MB/s nálam.

Ha a méret a fontos, akkor valamilyen LZMA alapú cucc kell (a PPM alapúak gyakorlati célokra használhatatlanok). Nem árt, ha a formátum szélesebb körben elterjedt; az xz-t választottam. Ezen belül kellett valami gyorsat keresni.

Mivel a darabolással párhuzamosítóknál az LZMA irdatlan szótármérete nem használható ki a legjobban, és itt a megtakarítás az elsődleges, azért csakis olyan program volt jó, ami nem darabol, hanem legfeljebb a fázisokat futtatja párhuzamosan ("adatcsatorna", hogy ELTE PP terminológiával éljek). Az xz ebbe az irányba tart (1), de tudtommal még nincs ott, a p7zip azonban már képes egy mag fölé menni. (Használt verzió: 9.20.1.)

A 7za-val az a gond, hogy nem unix-os, hanem dos-os a parancssora, valamint hogy mindenképpen ír az stderr-re/stdout-ra. Ezért csináltam köréje egy kis script-et (2). Ezt megmérve két magon 165%-os teljesítményt láttam. Olvasási sebesség (/usr/bin + /usr/lib-en) 1.8 MB/s, írási 416 KB/s, megtakarítás 77%. A skálázódás és az abszolút sebesség ugye itt másodlagos, ha gyors(ul), az bónusz.

Egy "általános" xz állomány kitömörítését eddig nem sikerült párhuzamosítanom semmilyen utility-vel, de szerencsére egy szálon is villámgyors. Mindenesetre a script-et úgy csináltam meg, hogy ha majd a p7zip bővül ilyen képességgel, akkor használja.

(1) As of writing (2010-09-27), it hasn't been decided if threads will be used by default on multicore systems once support for threading has been implemented. Comments are wel- come. The complicating factor is that using many threads will increase the memory usage dramatically. Note that if multithreading will be the default, it will probably be done so that single-threaded and multithreaded modes produce the same output, so compression ratio won't be significantly affected if threading will be enabled by default.

(2) "myxz" ill. "myunxz":


#!/bin/bash

set -e -u -C

BNAME=$(basename -- "$0")

if [ $# -ne 0 ]; then
  printf '%s: filter mode only\n' "$BNAME" >&2
  exit 1
fi

if [ x_"$BNAME" = x_myunxz ]; then
  if [ -t 0 ]; then
    printf "%s: won't read compressed data from a terminal\n" "$BNAME" >&2
    exit 1
  fi

  if [ -t 1 ]; then
    printf "%s: won't write decompressed data to a terminal\n" "$BNAME" >&2
    exit 1
  fi
else
  if [ -t 1 ]; then
    printf "%s: won't write compressed data to a terminal\n" "$BNAME" >&2
    exit 1
  fi
fi

ERRFILE=$(mktemp -t)
trap 'rm -f -- "$ERRFILE"' EXIT

set +e

if [ x_"$BNAME" = x_myunxz ]; then
  7za e           -bd -txz -mmt=on -si -so
else
  7za a /dev/null -bd -txz -mmt=on -si -so -mx=9 -ms=on -mf=off
fi 2>>"$ERRFILE"

RET=$?
set -e

if [ 1 -le $RET ] && [ $RET -le 127 ]; then
  cat -- "$ERRFILE" >&2
fi
exit $RET

A kapcsolók magyarázata, hogy ne kelljen bogarászni:

  • -bd

    : nincs progress indicator (amúgy sem értelmes pipe-ból, de így legalább nem szemeteli tele az stderr-t)

  • -txz

    : xz formátum

  • -mmt=on

    : több szál

  • -si -so

    : stdin-ről stdout-ra

  • -mx=9

    : "ultra" fokozat

  • -ms=on

    : "solid archive" (amúgy is ez az alapértelmezés, azt hiszem)

  • -mf=off

    : a p7zip eléggé el nem ítélhető módon tömörítéskor beleturkál azokba a futtatható file-okba, amelyekről valamiért úgy gondolja, hogy az újraírásukkal (asszem a branch instruction-ök "optimalizálásával") helyet lehet megtakarítani. Ez viccnek is rossz, úgyhogy gondolkodás nélkül kapcsoljuk ki; nekem veszteségmentes tömörítő kell, nem executable packer.

Hozzászólások


#!/bin/bash

set -e -u -C

A '-e' -t tutira ki lehet emelni a shebangba, de sztem a tobbit is.

lzma-nal a 9-es sebesseghez hozza tartozik, hogy nagyon memoriaigenyes, tehat kis memoriaju gepen a cucc nem hasznalhato.

Megmondom oszinten, en a bzip2-t kedvelem nagyon. Sebessegben nem sokban marad el a gzip-tol, tomesi aranya jobb, meg 7-es szinten is, ugyanakkor nem zabalja fel a gepet mikozben tom.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

A '-e' -t tutira ki lehet emelni a shebangba, de sztem a tobbit is.

Így van; az én ízlésemnek ez jobban megfelel.

lzma-nal a 9-es sebesseghez hozza tartozik, hogy nagyon memoriaigenyes, tehat kis memoriaju gepen a cucc nem hasznalhato.

Valóban, a 7za VSZ-je tömörítés alatt kb. 712M volt.

Megmondom oszinten, en a bzip2-t kedvelem nagyon.

Ennek örülök, mert így talán van olyan use case-ed, amelyre esetleg ajánlhatom az lbzip2-t :)

Mindenesetre innentől kezdve nem a két végletről beszélünk (nagyon gyors, vagy nagyon tömör), hanem valamiről a kettő között.

Sebessegben nem sokban marad el a gzip-tol, tomesi aranya jobb, meg 7-es szinten is

Az aránya kétségtelenül jobb, de hogy sebességben nem marad el a gzip-től? Ha az alapértelmezett tömörítési szinteket nézzük (437 MB

/usr/{bin,lib}

az input, többszálúaknál dual core + HT):


program  szint  idő[s]  méret[MB]
-------  -----  ------  ---------
bzip2    9      51      134
gzip     6      24      148

lbzip2   9      23      134
pigz     6      10      147

A gzip-nél a szintet 9-re emelve rendre 1M-et sikerült csak lefaragni a kimenetből, az idő viszont elszállt, mint a győzelmi zászló; úgyhogy a gzip szintjének az emelésével nem tudtam az összehasonlítást "egyenrangúvá" tenni (= azonos méretű kimeneten). Esetleg a bzip2 szintjének csökkentésével?

... A bzip2-nél a szintet 1-esre csökkentve az idő még mindig 46 mp (a méret 136M). Így ezen a bemeneti állományon a bzip2 legjobb sebessége még mindig csak kb. a fele a gzip default sebességének.

ugyanakkor nem zabalja fel a gepet mikozben tom.

A felzabáláson mit értesz, memóriát? Mert ha többszálú bzip2 tömörítőt használsz (szálszám-korlátozás ill. nice nélkül), az bizony megeszi alólad a CPU-t.

En vagyok olyan maradi, hogy egyszalu tomoritokkel dolgoztatok, reszben azert, mert egy agyonterhelt gepet nem terhel meg jobban szet, masfelol pedig ezek mindig elerhetoek a disztribucio reszekent, marpedig pl. egy RHEL eseteben ugye nem jo 3rdparty szoftvereket hasznalni, barmily hasznosak legyenek is azok.

Ami az idore vonatkozik: valoszinu, hogy a 9-es szint volt az, ami miatt elszallt az egesz. Default (7?) erteken tartva korulbelul hasonlo idokkel dolgozik - erzesre - mint a gzip. De ezek ilyen guessing adatok, sosem ultettem mogejuk egy time parancsot, hogy na most akkor ezt kimerjuk.

Azt is erdemes figyelembe venni, hogy production kornyezetben ezek az eszkozok egy egyebkent is terhelt diszkrol hajtjak vegre az olvasast, es nem biztos, hogy a disk cache mindig mellettuk lesz. Egy webszerveren a ritkabban lekert oldalak pont ugyanolyan fontosak, cserebe nem biztos, hogy benne lesznek a disk cache-ben.

Sok komponensu dolog ez, es nem is egyszeru ezekre a kerdesekre egzakt valaszokat adni.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal