LINUX.ORG.RU

Protothread для UNIX

 


0

0

Larry Ruane адаптировал идею сверхлегких бесстековых потоков Adam Dunkel к UNIX-подобным системам. Минимальный (два байта на поток) оверхэд и высокое быстродействие открывают широкие перспективы для новой технологии. Есть мнение, что модель потоков Larry Ruane более наглядна и удобна в отладке, чем традиционные нити.

Библиотека использует GCC label variables, не входящую в стандарт языка C.

>>> Подробности

★★

Проверено: Shaman007 ()
Ответ на: комментарий от tailgunner

> Так в каком месте COW сильно влияет на производительность
> _данного случая_?

извиняйте если я не о том, лень все читать...

COW все равно влияет. предположим процесс просто делает
if (!fork()) exit(). после этого у нас при каждой записи
в !MAP_SHARED память будет pagefault, not good.

или я не понял о чем спор?

idle ★★★★★
()
Ответ на: комментарий от idle

> COW все равно влияет. предположим процесс просто делает

> if (!fork()) exit(). после этого у нас при каждой записи

> в !MAP_SHARED память будет pagefault, not good.

Откуда возьмутся pagefault'ы? Имеются в виду вызовы atexit, или что?

> или я не понял о чем спор?

Какой-то из анонимных братьев выдвинул идею о том, что специальный вызов bugagaexec (эквивалентный CreateProcess, насколько я понял) будет заметно эффективнее fork+COW+exec. Вот я и пытаюсь выяснить, где источник этой эффективности :)

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

брат-анонимус. даже без write_process_memory я легко и непринуждённо поимею любой свой процесс на память через ptrace(2)
int *wraddr, *source, i;

ptrace(PTRACE_ATTACH, pid,...)

for(i=0; i<size; i++)
   ptrace(PTRACE_POKE_DATA, pid, wraddr++, source++);

только это будет божественно тормозить, но зато глаза краснющие!

anonymous
()
Ответ на: комментарий от anonymous

> http://www.slackware.ru/article.ghtml?ID=324 я решительно отказываюсь продолжать обсуждение с людьми, не знающими как реализован COW.

Твой пример if (!fork()) exit().

tailgunner спрашивал, откуда у тебя массовые пэйджфолты, если записи нету практически.

anonymous
()
Ответ на: комментарий от anonymous

Ещё линуксу нужен реестр как в виндоуз.

anonymous
()
Ответ на: комментарий от anonymous

COW наступает и в родительском процессе. в котором есть всякие стеки и прочая байда. пример: любая spawnящая программа, которая ессно хочет быть переносимой, и не знает о madvise(2) и прочих сложностях.

bugogaexec сейчас эмулируют парой vfork + exec, но в последней шаг влево-шаг вправо карается цугундером, и вообще можно вызвать только exec или _exit. а ведь можно бы было копировать только заранее припасённый маппинг ld-linux.so.2 перед самым стартом, COWать туда env + cmdline, и улетать нафих. это можно сделать даже библиотечно, через madvise, но помощь ядра с разделением vma всё равно потребовалась бы.

ЗЫ: A-234: в линухе сам по себе физический адрес бесполезен, все равно происходит поиск vma. кроме того, возникает сложность с копированием страницы: ведь её копию надо куда то мапнуть, развесить локи, чтоб соседние потоки фолтя ту же страницу не вызвали race condition и т.д и т.п. сам процесс копирования одной страницы - не подарок. а если программа если чем то полезным занималась, типа базу данных крутила? ох там полетят faultы.

//ckotinko

anonymous
()
Ответ на: комментарий от anonymous

специально для аналитиков с ЛОРа, manы

как линух обрабатывает pagefault
http://rus-linux.net/MyLDP/BOOKS/VirtMem/node46.html
как обрабатывается COW
http://rus-linux.net/MyLDP/BOOKS/VirtMem/node46.html#SECTION00105500000000000...
During fork, the PTE's of the TWO processes are made read-only so that when a write occurs there will be a page fault

TWO - это два по английски если кто не знает.

anonymous
()
Ответ на: комментарий от anonymous

>> Откуда возьмутся pagefault'ы? Имеются в виду вызовы atexit, или что?

> http://www.slackware.ru/article.ghtml?ID=324

Фундаментальная статья. Но даже из нее непонятно, откуда возьмутся pagefault'ы при записи, если процесс-потомок существует ровно столько, чтобы добежать до exit (или exec, если не отклоняться от темы). Или у него афигенной сложности функции atexit?

> я решительно отказываюсь продолжать обсуждение с людьми, не знающими как реализован COW.

Дело твое.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

c того что все PTE родительского процесса мало того что надо перелопатить, так их еще и pagefaultами потом накроет

или мы опять не рассматриваем родительский процесс, как и вызов malloc в лаже про 2 байта на поток?

anonymous
()
Ответ на: комментарий от anonymous

> c того что все PTE родительского процесса мало того что надо перелопатить

"Перелопатить", как завернул %) у процесса размером 128М - 32К PTE. Всего-то.

> так их еще и pagefaultами потом накроет

Минорными, продолжающимися до момента вызова exit/exec.

> или мы опять не рассматриваем родительский процесс

Мы всё рассматриваем.

В общем, гипотетический bugogaexec всего лишь убирает накладные расходы на организацию COW, и минорные pagefault'ы до момента вызова exec? Ну и чем это отличается от vfork+exec? Только не надо про "карается цугундером".

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

ладно, хватит сраццо.

http://www.informit.com/articles/article.aspx?p=370047&seqNum=2 Today, with copy-on-write and child-runs-first semantics, the only benefit to vfork() is not copying the parent page tables entries. If Linux one day gains copy-on-write page table entries there will no longer be any benefit.

правда возникает вопрос: как можно не копировать pte если например, родитель многопоточный на многопроцессорной же машине?

anonymous
()
Ответ на: комментарий от anonymous

> Где там запись, пальцем ткни.

if (!fork()) /* вот в это время любая запись в память в родительском процессе вызывает minor pagefault */ exit().

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

a)родитель может быть многопоточным. я не встречал во всяком случае информации о блокировании fork() всех потоков. например в лекциях SUN этого нет. стало быть на весь процесс кастуется COW немедленно, с рассылкой IPI процессорам о обновлении если надо cr3. так что первый тормоз налицо: IPI на процах + TLB flush + правка PDE(это быстрее) а.1)на core-duo требуется или резервная PDE с разметкой в ядро, или остановка всего процесса целиком. иначе анальная кара.

б)32k дескрипторов это аж 128к памяти. правда можно схитрить и поправить PDE(это 3Kb всего за вычетом ядра)

в)или pagefaultы на выбор, или exec должен повторить операцию a) для родительского потока еще раз, восстанавливая права на запись. первое позволяет растянуть тормоза во времени, второе - сократить их. но второе- дюже сложно на многопоточной программе, т.к. в это время еще могут быть pagefaultы на всех потоках, и чревато остановкой потоков в мутексах.

а bugogaexec от этой муры свободен, ему надо только создать task_struct, создать чистую mm, положить туда свежий ld-linux.so.2, положить туда vma с environment & argv и подать на вход 4 вольта.

anonymous
()
Ответ на: комментарий от anonymous

> родитель может быть многопоточным. я не встречал во всяком случае информации о блокировании fork() всех потоков

> первый тормоз налицо: IPI на процах + TLB flush + правка PDE

Это всё любопытно, но про fork() без цифр уже не интересно.

> а bugogaexec от этой муры свободен

Повторю вопрос: "Ну и чем это отличается от vfork+exec? Только не надо про "карается цугундером"."

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

карается цугундером - это означает что можно повредить память родительского процесса. так что следует прямиком валить в exec или exit

типа char **argv; int pid;

prepare_argv(&argv); if(pid=vfork()==0){ execvp(argv[0], argv); _exit(-1); } а смысл в том, что fork и exec занимаются как раз тем, чем занимался и bugogaexec. от форка там создание task_struct и mm(с одним только ld-linux.so.2), от exec его заполнение - добавление в mm чистого стека, выход на метку с настроенным стеком start:

это всё уже делается в ядре, но в двух syscallах. причем сам форк если и используется не для еxecа, то только через clone, который все равно не выкинут.

ЗЫ: торвальдс сам уже говорит о том что надо выбросить форк.

anonymous
()
Ответ на: комментарий от anonymous

> карается цугундером - это означает что можно повредить память родительского процесса

Это давно известно, описано в мане и всё такое. Для реализации spawn надо всего 1 раз сделать правильно.

[рассуждения о fork поскипаны]

Так будет ответ на вопрос, в чем выигрыш bugogaexec перед vfork+exec по производительности.

> торвальдс сам уже говорит о том что надо выбросить форк.

Ссылку?

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

> ЗЫ: торвальдс сам уже говорит о том что надо выбросить форк.

Пруфлинк. Форк в линуксе уже давно прямиком вызывает clone, как и vfork. Единственная функция, занимающаяся созданием новых задачек для проца - clone. В принципе, можно выкинуть fork и vfork из сисвызовов и оставить в глибце, хуже от этого никому не станет. Но это косметические изменения.

const86 ★★★★★
()
Ответ на: комментарий от tailgunner

начинаем stack unwinding

говорили о fork+exec? вижу, что вопрос снялся, fork тормоз.

далее, я писал anonymous (*) (19.01.2009 18:39:24) что vfork костыль. это так, но я не сказал что его надо взять и выкинуть. на текущий момент это проблематично в силу униксоподобной архитектуры

anonymous
()
Ответ на: комментарий от anonymous

> начинаем stack unwinding

Если можешь, начни со ссылки "Торвальдс хочет выбросить fork"

> говорили о fork+exec? вижу, что вопрос снялся, fork тормоз.

Вопрос не снят - он доведен до состояния, где уже нужны цифры. Цифр у меня нет, ты их тоже не приводишь.

> далее, я писал

Я вас, анонимусов, не различаю. Меня интересует тот, который сказал, что надо реализовывать bugogaexec(2) - у меня к нему вопрос, который я уже несколько раз задал: в чем выигрыш bugogaexec перед vfork+exec по производительности?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> > COW все равно влияет. предположим процесс просто делает > > if (!fork()) exit(). после этого у нас при каждой записи > > в !MAP_SHARED память будет pagefault, not good. > > Откуда возьмутся pagefault'ы? Имеются в виду вызовы atexit, > или что?

нет. child быстро завершается, но результат ptep_set_wrprotect() никто не отменял. поэтому родительский процесс после этого будет иметь VM_FAULT_WRITE при каждой записи в страницу.

то есть, fork+COW+exec кроме накладных расходов на собственно dup_mm() имеет еще и "отложенный" эффект.

idle ★★★★★
()
Ответ на: комментарий от tailgunner

> > COW все равно влияет. предположим процесс просто делает
> > if (!fork()) exit(). после этого у нас при каждой записи
> > в !MAP_SHARED память будет pagefault, not good.
>
> Откуда возьмутся pagefault'ы? Имеются в виду вызовы atexit,
> или что?

нет. child быстро завершается, но результат ptep_set_wrprotect()
никто не отменял. поэтому родительский процесс после этого будет 
иметь VM_FAULT_WRITE при каждой записи в страницу.

то есть, fork+COW+exec кроме накладных расходов на собственно
dup_mm() имеет еще и "отложенный" эффект.

но что-то я уже запутался здесь... если мы говорим про
vfork() + exec(), тогда я не думаю, что специальный вызов
будет быстрее.

idle ★★★★★
()
Ответ на: комментарий от tailgunner

>в чем выигрыш bugogaexec перед vfork+exec по производительности?

начнём с того, что вы писали не про vfork, а про fork+COW:

>Просто расскажи, чем (в плане производительности) fork+COW+exec

>отличается от CreateProcess или bugagaexec.

>tailgunner *** (*) (19.01.2009 22:45:30)


не надо тут ляля.
тесты под linux 2.6 glibc 2.5
http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2007-06/msg00789.html
>~$ time ./fork_test 10000

>3.28s user 5.87s system 99% cpu 9.187 total

>~$ time ./vfork_test 10000

>2.66s user 4.25s system 99% cpu 6.947 total


вопрос по spawn(2) уже обуждался:
http://lkml.indiana.edu/hypermail/linux/kernel/0104.1/1014.html
>spawn() is TRIVIAL to implement if you want to.

>I don't think it's all that much more interesting

>than vfork()+execve(), though. Linus


bugogaexec - имплементится тривиально. 1 syscall вместо 2х. проблема же в другом: часто надо произвести промежуточные действия. а тут или COW, или vfork жёппу отрежет. на практике vfork можно использовать но надо после него вызывать функцию с полезным кодом, что загородиться stack frame от повреждения стека родительского процесса.

//ckotinko

anonymous
()
Ответ на: комментарий от anonymous

> начнём с того, что вы писали не про vfork, а про fork+COW:

>>Просто расскажи, чем (в плане производительности) fork+COW+exec

>>отличается от CreateProcess или bugagaexec.

>>tailgunner *** (*) (19.01.2009 22:45:30)


Ну и? Я просил рассказать, ты рассказал. Дальше я не стал продолжать без цифр, о чем честно сказал. Что не так?

> не надо тут ляля.


Ну так ты обоснуешь, зачем нужен новый bugagaexec(2), или будешь докапываться до того, что я по ходу дискуссии посмел задать второй вопрос?

>тесты под linux 2.6 glibc 2.5


>http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2007-06/msg00789.html


Ура, цифры!

<Ъ>

~$ time ./spawn_test 10000
2.70s user 4.28s system 99% cpu 7.004 total
~$ time ./fork_test 10000
3.28s user 5.87s system 99% cpu 9.187 total

</Ъ>


4.28/5.87 == 0.73

17% системного времени убрано на тривиальной программе в плотном цикле, вот весь выигрыш spawn (vfork+exec) перед fork+COW+exec. И мы снова возвращаемся к вопросу сравнения теоретического bugagaexec с vfork+exec :D

>вопрос по spawn(2) уже обуждался:


>http://lkml.indiana.edu/hypermail/linux/kernel/0104.1/1014.html


>>spawn() is TRIVIAL to implement if you want to.


Это ссылка о чем? О том, что новый сисколл не нужен, или о том, что Линус не против fork?

> bugogaexec - имплементится тривиально


к черту его тривиальность, профит в чем?

> на практике vfork можно использовать но надо после него вызывать функцию с полезным кодом


Блин, spawn _уже_ реализован, где профит bugagaexec по сравнению с vfork+exec - 1 сэкономленный сисколл? Да он утонет в шуме загрузки нового образа, которой не избежать по-любому.

tailgunner ★★★★★
()
Ответ на: комментарий от iZEN

>... причём одно на другое как-то не влияет даже (костыль здесь — костыль там). iZEN ***

^^^ и инвалид здесь

Hug37r011
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.