Jo, skvelej text, jako vetsina veci od fefeho. Rekl bych ale ze rika neco trochu jineho nez Mikulas tady.
Jeho hlavni argument, v kterem se s Mikulasem neshodnou, je ze fork() pomalej NENI, je jenom blbe implementovanej. Thready a select(), poll(), kqueue(), epoll() apod jsou nesmyslne berlicky na spatnem miste.
A protoze to vypada ve v 2.6 jadru je konecne vytvareni i ruseni procesu O(1) zalezitost, mohli bychom mozna konecne prestat ty pitomy thready nebo pollovaci smycky konecne prestat pouzivat :)
Taktez bych se pripojil k tvrzeni ze fork() neni
pomaly. Teda aspon v pripade FTP serveru, jak tvrdi clanek. Fork() je na vetsine systemu dostatecne rychly (neni prilis pomalejsi nez vytvoreni threadu). Jedina vyjimka je proces s velkym mnozstvim VM regionu. Pak je treba prochazet strankove tabulky a nastavovat r-only pro pozdejsi copy-on-write. Ale normalni server (jako treba Apache nebo FTP server) tohle vubec nepozna.
Vlastni provoz vice procesu (oproti vice threadum) by byl pomaly, pouze pokud by kazdy proces/thread musel na neco interaktivne reagovat (a tedy se casto probouzet a usinat). Pri kazdem prepnuti procesu (oproti threadu) je treba vylit TLB, coz na x86 muze byt pomale. Ale treba UltraSparc si muze pamatovat uvnitr procesu nekolik posledne pouzitych kontextu, takze ani vyliti TLB pro prepnuti kontextu nemusi byt prilis zdrzujici.
No a v clanku uvedeny FTP server jako priklad uz vubec tohle nesplnuje. FTP server pracuje tak, ze vetsinu casu travi v jadre v nejakem velkem write(2) nebo jeste vetsim sendfile(2). Akorat se jednou za pet minut probudi pres SIGALRM aby zjistil, jestli jeste klient nezdechl.
S druhou casti predchoziho komentare (ze kqueue nebo epoll neni k nicemu) se ovsem neshodnu. Muze to mit svuj ucel, ale nikoliv u FTP serveru, kde v podstate vsechno probiha v jadre a prepinani procesu nema zadny vliv.
A treti cast predchoziho komentare (vytvareni procesu a ruseni procesu je O(1)) je take diskutabilni, protoze neni jasne vzhledem k cemu je O(1). Vzhledem k poctu procesu urcite, ale treba vzhledem k poctu VM regionu urcite ne. Tam je zavislost rekl bych linearni. Cili nekdy muze byt
i vytvoreni procesu docela drahe.
-Yenya
> Jedina vyjimka je proces s velkym mnozstvim VM regionu. Pak je treba prochazet strankove tabulky a nastavovat r-only pro pozdejsi copy-on-write.
Nejak nerozumim. R-only se nastavuje pro stranku, nikoliv pro region, ne? Takze pomaly by mel(?) byt i fork() jednoho velkeho R-W VM regionu.
> Pri kazdem prepnuti procesu (oproti threadu) je treba vylit TLB, coz na x86 muze byt pomale.
Tohle bylo docela dobre analyzovano, doba "naliti" TLB po switchi je ve srovnani s periodou planovace smesne mala. 2.6ka planuje jeste o neco pomaleji, takze rezie flushnuteho TLB je hluboko pod setinami procenta. Velmi mala cena za to ze se clovek zbavi problemu s nereentrantnimi knihovnami a pomalym a neportabilnim pristupem k TLS.
> Nejak nerozumim. R-only se nastavuje pro stranku,
> nikoliv pro region, ne? Takze pomaly by mel(?) byt
> i fork() jednoho velkeho R-W VM regionu.
Ano, to taky. To jsem jen explicitne neuvedl.
Co se tyce rezie TLB flush, tady je jeste jeden aspekt - u threadu je stejna VM, takze i thready sdileji nacachovana data a instrukce v cache CPU. U procesu tomu tak neni (aspon u r/w dat; instrukce sdileny byt mohou - pokud jsou sdileny na urovni OS pomoci copy-on-write). Cili k vyliti TLB (zmeritelnemu) je treba precist znovunaplneni cache (a to je pro kazdy workload jine).
-Yenya
No, i nejhorsi pripad (2MB cache) je stale docela akceptovatelny:
http://kerneltrap.org/node/view/517
..on a sufficiently powerful CPU with a 2 MB L2 cache, the 'population time' of the cache can be as high as 10 milliseconds. So if there are two numeric calculation tasks that both fully utilize the L2 cache (in nonobvious patterns), and which context-switch every 150 milliseconds, then they will waste 10 milliseconds on cache-rebuilding in the first 6% of their timeslice. This shows up as a direct 6% slowdown of the numeric calculation jobs. Now, if SCHED_BATCH is used, and each task has a 3000 milliseconds timeslice, then the cache-rebuild overhead can be at most 0.3% - a far more acceptable number... this is also one of the reasons why the default timeslice length got almost doubled over the 2.4 scheduler's timeslice length (there it was 80 msecs).
To je ovsem o vypocetnich procesech, ktere se prepinaji po 150 milisekundach (cili cili 7x za sekundu). Na svem FTP serveru vidim prave ted 1449 prepnuti kontextu za sekundu (nastesti vetsina je uvnitr jadra v sendfile(), takze se dela lazy TLB flush a tento problem se neprojevi). Ale pokud by se vse delalo v user-space, tak 10ms na naplneni cache je opravdu dost.
-Yenya
Realtimove signaly sice standardizovany jsou, ale jejich pouziti pro cekani na udalosti ne.
fcntl(h, F_SETFL, FASYNC) v POSIXu nevidim. V *BSD to sice je, ale misto FASYNC se pouziva O_ASYNC. (Viz http://netbsd.gw.com/cgi-bin/man-cgi?fcntl nebo http://www.freebsd.org/cgi/man.cgi). A fcntl(h, F_SETSIG, signal) je cisty linuxismus. Zadne prenositelne a pritom skalovatelne API pro cekani na udalosti neni.