On Thursday 26 August 2004 12:50, Peter Pentchev wrote: --cut-- > Това 899981 се получава от bzip2, няма нищо общо с tar. В сорса на > bzip2, bzlib.c, функцията BZ2_bzCompressInit(), около ред 238: > > s->nblockMAX = 100000 * blockSize100k - 19; > > Това е unconditional, изобщо не зависи от това, което bzip2 много > по-късно ще прочете от входния си файл. Размерът на блока, който bzip2 > компресира, е 100000 байта * колкото си му казал - 19; така при 'колкото > си му казал' == 9 се получава точно 899981.
даа видях го, макар, че не бих и предположил както и сега не мога да стопля защо се прави това за новия блок, явно се има нещо предвид... както и да е няма значение. Наистина така както е написан не можем да му спестим реблокването. Сега се убедих в това. > > значи първо не сме сигурни дали tar и bzip2 write()-ват и read()-ват > > цели блокове или цели записи или части от записи от по 512 байта. > > За tar сме на практика сигурни, че write-ва блокове; нали това е цялата > идея на параметъра block size - че някои лентови устройства са си > истински block devices и могат да четат и пишат *само* на блокове, така > че единственият начин tar да успее изобщо да запише нещо е да подаде цял > блок в един write(). мда правилно, май за тар ще трябва да се съглася ;-) > За bzip2... там се оказа странно :) Сорса на bzip2, bzip2.c, функцията > compressStream(), около ред 444: > > while (True) { > > if (myfeof(stream)) break; > nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream ); > if (ferror(stream)) goto errhandler_io; > if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf ); > if (bzerr != BZ_OK) goto errhandler; > > } леле, как не те мързя да ги изкопаш тези работи... ще видя дали ще се ориентирам по-късно в тях ... > Най-важен е редът с nIbuf = fread(..., 1, 5000, ...) - оказва се, че > bzip2 използва stdio за четене, и си взима входа по 5000 байта наведнъж. > Разбира се, това не значи, че bzip2 чете по 5000 байта на syscall - > част от идеята на библиотеката stdio е да буферира и входа, и изхода, > така че всъщност четенето се прави на блокове с размер, указан в > стандартната константа BUFSIZ, дефинирана в stdio.h. Разбира се, тази > стойност е различна за различните реализации на библиотеката stdio, > макар че изглежда, че за няколко различни варианта на Linux (всичките с > glibc) все е 8192. Под FreeBSD пък се оказа 1024. т.е. за линукс това е дефиницията: _G_config.h:#define _G_BUFSIZ 8192 нямам фрийзби сега да видя, но ще ти повярвам, че е колкото казваш ;-) > Демек, каквито и магии да правим с tar -b и bzip2 -1..9, всичко, което > bzip2 някога ще успее да направи със syscalls, ще бъде да чете по BUFSIZ > байта от входния пайп - BUFSIZ, ни повече, ни по-малко. Оттук нататък > *може би* може да се постигне някакво ускорение, ако се опитаме да > убедим tar да подава по горе-долу толкова байта, но не съм много > сигурен: тогава пък може да се сблъскаме с буферирането на данни в > пайпове от самото ядро, което може да не позволи предаване на 8KB > наведнъж. За FreeBSD може и да успее - ако има достатъчно памет и > mbufs, като нищо може да увеличи размера на пайпа и над 4KB, само че > това няма много смисъл, след като bzip2 ще чете само по 1KB. За Linux закачен за бзип2 (след паип от тар) strace показва че read()-ва по 4КБ. (размера на кое точно е това не можах да установя ;-) > не съм много сигурен, но от това, което сега гледам в > arch/i386/kernel/sys_i386.c, fs/pipe.c и няколко header файла, изглежда, > че гаранция за атомично писане има при опит за писане на не повече от > 4KB, а максималният размер на самия пайп е PAGE_SIZE, което при i386 > според include/asm/page.h кажи-речи винаги е... ами.. таковата.. 4KB :) Значи PAGE_SIZE е физическия размер на странирането на паметта от страна на процесора. Имаме и системен размер на страниране (т.е. страниране на виртуалната памет). И двете могат да се променят и да бъдат различни за разните процеси дори и рънтайм: http://www.gnu.org/software/libc/manual/html_node/Query-Memory-Parameters.html ако наистина размера на атомик писане в пайп е размера на страница от виртуалната или физическата памет, то последните размери май могат да бъдат променени. Не ме питай как ;-) > Накратко, оптимизация на syscalls на bzip2 на практика не може да бъде > направена - не и при положение, че tar му подава всичко през пайп :( Да наистина бзип2 винаги ще си прави новия блок както е закодирано в неговия сорс. Но дали ще може да му се увеличи от пайпа да чете по-повечко байта на сискол ? В крайна сметка, май прекаляваме, тръгнали сме да увеличаваме производителността на компресор. Май наистина няма смисъл. > > Та това може да не е размера на блока който получава bzip2, а който > > обработва явно след реблокване. Предлагам да не гадеам повече. > > Надявам се, че горното малко разсея мъглата, макар и да достигна до > съвсем странни изводи :) > > > Освен това, не е казано, че трябва двете приложения да се пайпват, ако > > имаме съмнения, че предаването в пайпа може да се бави поради разни > > причини (tar --options; bzip2 --options) > > Единственият начин да не ги пайпваш е да направиш tar -cf fname.tar foo > и после отделно bzip2 -9 fname.tar. При това ще избегнеш наистина > ограниченията, наложени от пайповете, но пък тогава вече няма да има > абсолютно никакво значение - ама наистина абсолютно никакво - какъв > размер на блок се избира за tar :) Ами май и тук си прав. Нещата стават доста сложни и не е за имейл тази работа. Край предавам се: no more block tips&tricks. -- pub 4096R/0E4BD0AB 2003-03-18 <keyserver.bu.edu ; pgp.mit.edu> fingerprint 1AE7 7C66 0A26 5BFF DF22 5D55 1C57 0C89 0E4B D0AB ============================================================================ A mail-list of Linux Users Group - Bulgaria (bulgarian linuxers). http://www.linux-bulgaria.org - Hosted by Internet Group Ltd. - Stara Zagora To unsubscribe: http://www.linux-bulgaria.org/public/mail_list.html ============================================================================