Re: lug-bg: влияние на размера на блока
- Subject: Re: lug-bg: влияние на размера на блока
- From: Peter Pentchev <roam@xxxxxxxxxxx>
- Date: Thu, 26 Aug 2004 12:50:44 +0300
On Thu, Aug 26, 2004 at 11:06:03AM +0300, George Danchev wrote:
> On Wednesday 25 August 2004 15:14, Peter Pentchev wrote:
> > On Wed, Aug 25, 2004 at 02:53:42PM +0300, George Danchev wrote:
> > > On Wednesday 25 August 2004 13:17, Peter Pentchev wrote:
> > > --cut--
> > >
> > > > Какво точно искаш да кажеш с това 'да получи на вход'? Ако имаш
> > > > предвид да се даде на tar опция -b 1800, така че то да прави write() на
> > > > парчета от 900KB и bzip2 да получава по 900KB при всеки read(), аз
> > > > виждам два възможни сериозни проблема с това:
> > >
> > > Мда, точно така, не виждам нищо лошо в:
> > > tar cf - dir -b 1800 | bzip2 > dir.tar.bz2
> >
> > Значи да попитам пак: смяташ, че ако размерът на изходния блок на tar е
> > равен на размера на входния блок на bzip2, това ще доведе до повишаване
> > на производителността, така ли? Един малко тъп въпрос: защо? Т.е. как?
> > Т.е. какво точно смяташ, че ще се подобри?
>
> ами точно както си си отговорил по-долу, имах предвид да се намали сискол
> овърхеда от реблокинг при bzip2.
Мдаааа... оказа се, че майтапът е пълен; виж по-долу относно начина,
по който bzip2 всъщност чете :)))
> > Единственото, което на мен ми се струва възможно да се подобри, е това
> > bzip2 да си получава входа с по-малко работа, т.е. с по-малко syscalls,
> > т.е. да получава по 900KB (или по-точно по 899981 байта) при всяко
> > извикване на read() - а това е *точно* това, което смятам, че няма начин
> > да стане :) Ако имаш някаква друга идея за това как точно ще се подобри
> > работата на bzip2, ако на tar му зададеш -b 1800, казвай!
>
> имаме: block = [record size (кратно на 512)] x [blocking factor]
> това 899981 за сега нямам идея защо се получава, но се получава при разни
> стойности на -b:
Това 899981 се получава от bzip2, няма нищо общо с tar. В сорса на
bzip2, bzlib.c, функцията BZ2_bzCompressInit(), около ред 238:
s->nblockMAX = 100000 * blockSize100k - 19;
Това е unconditional, изобщо не зависи от това, което bzip2 много
по-късно ще прочете от входния си файл. Размерът на блока, който bzip2
компресира, е 100000 байта * колкото си му казал - 19; така при 'колкото
си му казал' == 9 се получава точно 899981.
> Да се намали сискол овърхеда от реблокинг при bzip2. Това е
> единственото което можем да се опитаме да си спестим според мен.
Мда, и аз за това говоря наистина от самото начало, само че се оказва,
че ключът от бараката е на съвсем, ама съвсем друго място.. виж малко
по-долу.
> > > Според мен ядрото няма да бута в пайпа наведнъж всичките 899981 байта ;-)
> > > горната команда ще мине и на фрийсби, почти съм сигурен... просто тези
> > > 899981 байта ще бъдат подадени на по-малки части и това си е работа на
> > > ядрото мисля да контролира двата края на пайпа и колко влиза и колко
> > > излиза в и от тях.
> >
> > Така де, така - и точно затова ядрото и от двата края на пайпа не
> > поддържа блокове по 899981, следователно bzip2 няма начин да прочете
> > наведнъж 899981 байта - и с какво ще се подобри работата му тогава?
> > Особено при положение, че 1800 * 512 != 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.
Демек, каквито и магии да правим с tar -b и bzip2 -1..9, всичко, което
bzip2 някога ще успее да направи със syscalls, ще бъде да чете по BUFSIZ
байта от входния пайп - BUFSIZ, ни повече, ни по-малко. Оттук нататък
*може би* може да се постигне някакво ускорение, ако се опитаме да
убедим tar да подава по горе-долу толкова байта, но не съм много
сигурен: тогава пък може да се сблъскаме с буферирането на данни в
пайпове от самото ядро, което може да не позволи предаване на 8KB
наведнъж. За FreeBSD може и да успее - ако има достатъчно памет и
mbufs, като нищо може да увеличи размера на пайпа и над 4KB, само че
това няма много смисъл, след като bzip2 ще чете само по 1KB. За Linux
не съм много сигурен, но от това, което сега гледам в
arch/i386/kernel/sys_i386.c, fs/pipe.c и няколко header файла, изглежда,
че гаранция за атомично писане има при опит за писане на не повече от
4KB, а максималният размер на самия пайп е PAGE_SIZE, което при i386
според include/asm/page.h кажи-речи винаги е... ами.. таковата.. 4KB :)
Накратко, оптимизация на syscalls на bzip2 на практика не може да бъде
направена - не и при положение, че tar му подава всичко през пайп :(
> Та това може да не е размера на блока който получава bzip2, а който обработва
> явно след реблокване. Предлагам да не гадеам повече.
Надявам се, че горното малко разсея мъглата, макар и да достигна до
съвсем странни изводи :)
> Освен това, не е казано, че трябва двете приложения да се пайпват, ако имаме
> съмнения, че предаването в пайпа може да се бави поради разни причини (tar
> --options; bzip2 --options)
Единственият начин да не ги пайпваш е да направиш tar -cf fname.tar foo
и после отделно bzip2 -9 fname.tar. При това ще избегнеш наистина
ограниченията, наложени от пайповете, но пък тогава вече няма да има
абсолютно никакво значение - ама наистина абсолютно никакво - какъв
размер на блок се избира за tar :)
Поздрави,
Петър
--
Peter Pentchev roam@xxxxxxxxxxx roam@xxxxxxxx roam@xxxxxxxxxxx
PGP key: http://people.FreeBSD.org/~roam/roam.key.asc
Key fingerprint FDBA FD79 C26F 3C51 C95E DF9E ED18 B68D 1619 4553
This sentence was in the past tense.
Attachment:
pgptRDj0xmqV6.pgp
Description: PGP signature
|