LINUX.ORG.RU

контексты vs файберы


0

1

собственно, пояснение: в венде, для операций с контекстами выполнения используются файберы(fibers). в доке говорится что они реализованы очень схоже с потоками за исключением того, что позволяют пользовательскому коду самому управлять контекстом управления. минус файберов в том, что они(как и потоки) по умолчанию резервируют 1МБ виртуальной памяти, вне зависимости от того, какой объем стека для них указан. т.е. если объем стека меньше 1МБ, то объем виртуальной памяти всегда 1МБ. для сопрограмм, как правило, такие огромные стеки не нужны. обычно объем стека находится в пределах 8-64Кб. т.е. уменьшая объем стека, мы экономим физическую память, но виртуальная память неподконтрольна. т.е. создать 100000 файберов - проблематично.

аналогичная технология в линуксе - контексты[1,2]. но я никак немогу понять, используют ли они виртуальную память, растет ли необходимый объем виртуальной памяти при росте кол-ва контекстов, и какова зависимость между размером стека для контекста и размером виртуальной памяти?

очень много гуглил - но ничего говорящего _о_виртуальной_памяти_для_контекстов_ не нашел.

благодарен.

[1] http://linux.die.net/man/3/makecontext [2] http://linux.die.net/man/3/getcontext

★★★

Последнее исправление: niXman (всего исправлений: 1)

По Вашим же ссылкам написано, что контексты - устаревшая фича, т.е. использовать её не надо.

Sorcerer ★★★★★
()

Может посмотреть в сторону «лёгких» процессов, как в Erlang? Не думаю, что средствами ОС можно сделать достаточно большое количество потоков без больших затрат на память.

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

в надежде на таких умельцев как Вы.

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

господа, ну почему вы позволяете себе оффтопить? разве я где-то писал о том, что собираюсь их использовать?

спасибо за понимание.

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

man optimistic memory allocation

man malloc

NOTES
       By default, Linux follows an optimistic memory allocation strategy.  This means that when malloc() returns non-NULL there is no guarantee that the memory really is available.  In case it turns out that the system is  out  of
       memory,  one  or  more  processes  will  be  killed  by  the OOM killer.  For more information, see the description of /proc/sys/vm/overcommit_memory and /proc/sys/vm/oom_adj in proc(5), and the kernel source file Documenta‐
       tion/vm/overcommit-accounting.

       Normally, malloc() allocates memory from the heap, and adjusts the size of the heap as required, using sbrk(2).  When allocating blocks of memory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation  allocates
       the  memory  as  a private anonymous mapping using mmap(2).  MMAP_THRESHOLD is 128 kB by default, but is adjustable using mallopt(3).  Allocations performed using mmap(2) are unaffected by the RLIMIT_DATA resource limit (see
       getrlimit(2)).

       The UNIX 98 standard requires malloc(), calloc(), and realloc() to set errno to ENOMEM upon failure.  Glibc assumes that this is done (and the glibc versions of these routines do this); if you use a private malloc  implemen‐
       tation that does not set errno, then certain library routines may fail without having a reason in errno.

       Crashes in malloc(), calloc(), realloc(), or free() are almost always related to heap corruption, such as overflowing an allocated chunk or freeing the same pointer twice.

       Recent  versions  of  Linux libc (later than 5.4.23) and glibc (2.x) include a malloc() implementation which is tunable via environment variables.  When MALLOC_CHECK_ is set, a special (less efficient) implementation is used
       which is designed to be tolerant against simple errors, such as double calls of free() with the same argument, or overruns of a single byte (off-by-one bugs).  Not all such errors can be protected against, however, and  mem‐
       ory leaks can result.  If MALLOC_CHECK_ is set to 0, any detected heap corruption is silently ignored; if set to 1, a diagnostic message is printed on stderr; if set to 2, abort(3) is called immediately; if set to 3, a diag‐
       nostic message is printed on stderr and the program is aborted.  Using a nonzero MALLOC_CHECK_ value can be useful because otherwise a crash may happen much later, and the true cause for the problem  is  then  very  hard  to
       track down.
но опять же, тут ничего не говорится о требованиях к виртуальной памяти, относительно реальной. и ничего не говорится о реализации контекстов и влиянии их кол-ва на виртуальную память.

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

а так? By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. In case it turns out that the system is out of memory, one or more processes will be killed by the OOM killer. For more information, see the description of /proc/sys/vm/overcommit_memory and /proc/sys/vm/oom_adj in proc(5), and the kernel source file Documenta‐ tion/vm/overcommit-accounting.

nanoolinux ★★★★
()

файберы(fibers)

«Волокна», епт.

контексты[1,2]. но я никак немогу понять, используют ли они виртуальную память

Странный вопрос. _Всё_ использует виртуальную память.

растет ли необходимый объем виртуальной памяти при росте кол-ва контекстов, и какова зависимость между размером стека для контекста и размером виртуальной памяти?

Наверное, ты хочешь спросить, выделяется ли виртуальная память под стек контекста? Нет, автоматически не выделяется. Об этом прямо сказано в документации:

Before invoking makecontext(), the caller must allocate a new stack  for  this  context and assign its address to ucp->uc_stack
tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Наверное, ты хочешь спросить, выделяется ли виртуальная память под стек контекста? Нет, автоматически не выделяется. Об этом прямо сказано в документации:

да, это я и хотел спросить. не знал как доходчивее это сделать, и получилось как всегда..

спасибо, вопрос решен!

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

можно добавить, что стандартный swapcontext делает достаточно много работы, которая в конкретном случае может оказаться невостребованной (сохраняет сигналы, состояние всяких xmm и пр.).

если точно знаешь, чем ты из этого пользуешься, и нужна высокая производительность, то имеет смысл написать свой swapcontext, который будет сохранять только необходимую часть контекста.

я уже не помню конкретных результатов, но вроде как, немного повозившись, получил на cortex-a9 ~20 миллионов переключений контекста в секунду, что, судя по тому, как я этому радовался, было сильно быстрее, чем библиотечными функциями.

anonymous
()

Нет, никаких автоматических выделений не происходит. Стек ты выделяешь сам и волен делать его 256-байтным.

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

спасибо за информацию.

скажите, а что нужно сделать, чтоб посмотреть то, из чего вы получили такую скорость? ;)

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

Уже давно написан. Называется _setjmp и _longjmp.

на моей системе (archlinux x86_64):

$ objdump -d /lib/libc.so.6 | grep -A2 '<_setjmp>:' 
0000000000034df0 <_setjmp>:
   34df0:	31 f6                	xor    %esi,%esi
   34df2:	e9 59 ff ff ff       	jmpq   34d50 <__sigsetjmp>

а я как раз предлагал забить на сигналы.

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

а я как раз предлагал забить на сигналы.

ок, я не прав, __sigsetjmp не сохраняет сигналы, когда его так вызывают (savesigs@esi==0).

но все равно, если выкинуть все эти проверки и заинлайнить все, будет гораздо быстрее. по крайней мере, по моему опыту.

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

а я как раз предлагал забить на сигналы.

Ты для начала матчасть подучи, а потом уже ксакепские дампы приводи. _setjmp и _longjmp отличаются от своих стандартизованных аналогов тем, что не сохраняют маску сигналов.

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

Ты для начала матчасть подучи

уже, спасибо.

а потом уже ксакепские дампы приводи

мне си на работе хватает, и желания читать сорцы (и билдсистему) glibc у меня нет.

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

ок, я не прав, __sigsetjmp не сохраняет сигналы, когда его так вызывают (savesigs@esi==0).

От же ты хардкорный. У glibc есть исходники.

но все равно, если выкинуть все эти проверки и заинлайнить все, будет гораздо быстрее

Зато setjmp и longjmp гарантированы стандартом => работают везде, а _setjmp и _longjmp практически гарантированно обгоняют swapcontext, потому что не манипулируют сигналами.

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

где можно увидеть сорцы?

ну picoro — по ссылке выше.

мою версию — думаю, нигде, это был внутренний исследовательский проект (и на корутины мы тогда все-таки забили).

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

вопрос о том, где можно увидеть сорцы?

Не парься и бери libcoro. Вся магия там уже сделана за тебя.

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