[trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 03.07.13 14:59
Оценка: 64 (6)
Эмуляция оператора await из языка C# 5.
Данный proof-of-concept показывает, что идентичный синтаксис оператора await может быть достигнут с помощью Stackful Coroutines, демонстрируя что они предоставляют превосходящие возможности.
Цель данного proof-of-concept — привлечь внимание к Stackful Coroutines, а не эмуляция await'а сама по себе — так как с помощью сопроцедур можно достичь более высоких уровней инкапсуляции
Автор: Evgeny.Panasyuk
Дата: 21.06.13
.
Пример использования:
int bar(int i)
{
    // await is not limited by "one level" as in C#
    auto result = await async([i]{ return reschedule(), i*100; });
    return result + i*10;
}

int foo(int i)
{
    cout << i << ":\tbegin" << endl;
    cout << await async([i]{ return reschedule(), i*10; }) << ":\tbody" << endl;
    cout << bar(i) << ":\tend" << endl;
    return i*1000;
}

void async_user_handler()
{
    vector<future<int>> fs;

    // instead of `async` at function signature, `asynchronous` should be
    // used at the call place:
    for(auto i=0; i!=5; ++i)
        fs.push_back( asynchronous([i]{ return foo(i+1); }) );

    for(auto &&f : fs)
        cout << await f << ":\tafter end" << endl;
}

"Оператор" await принимает std::future-like объект с поддержкой продолжений (например .then) и возвращает результат future (await future<int>(...), вернёт int).
В данном примере используется boost::async. Но такой подход может использоваться и с другими видами future, например PPL task::then и т.д.
Вывод:
1:      begin
2:      begin
3:      begin
4:      begin
5:      begin
20:     body
10:     body
30:     body
110:    end
1000:   after end
50:     body
220:    end
2000:   after end
550:    end
40:     body
330:    end
3000:   after end
440:    end
4000:   after end
5000:   after end

Re: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Шахтер Интернет  
Дата: 03.07.13 18:01
Оценка: +3 -2
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Я вот лет 10 назад экспериментировал с корутинами. Сделал реализацию под студию. Насколько я понимаю, аналогичная реализация сейчас добавлена в boost.
И так с тех пор она мне не пригодилась. Мне всё-таки кажется, что это всё мертворождённо. На современных многоядерных процессорах можно не изобретать псевдо-потоки,
а проще и выгодней пользоваться настоящей многопоточностью с настоящим параллелизмом.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 03.07.13 19:41
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Мне всё-таки кажется, что это всё мертворождённо. На современных многоядерных процессорах можно не изобретать псевдо-потоки,

Ш>а проще и выгодней пользоваться настоящей многопоточностью с настоящим параллелизмом.

А тут дело не только в псевдо/green-потоках.
Весь шум из-за того, что await это один из способов распрямить код использующий результаты "асинхронных" вызовов без блокирования вызывающего потока, сделать implicit continuations. Сами вызовы необязательно выполняются в одном потоке — в примере выше по async может использоваться пул реальных потоков.

Саттер, в последнем выступлении на C9, показывал примеры асинхронного кода WinRT и сказал что возможно в C++ добавят await.
Я не то чтобы совсем против await'а, но я в первую очередь предпочту сначала нормальные stackful coroutines — они намного мощнее await'а и как показывает пример выше на них можно легко реализовать как await-like код (для чего собственно я и сделал proof-of-concept), так и много чего другого.
Во-вторых, имхо, добавить stackful coroutines в ISO будет легче, чем await. В Boost.Coroutine сейчас довольно лаконичный интерфейс. А функции с await наверняка будут иметь много ограничений, либо спецификация будет громоздкой (C++ это всё-таки не C#).
Re[2]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: enji  
Дата: 04.07.13 08:10
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Evgeny.Panasyuk, Вы писали:


Ш>Я вот лет 10 назад экспериментировал с корутинами. Сделал реализацию под студию. Насколько я понимаю, аналогичная реализация сейчас добавлена в boost.

Ш>И так с тех пор она мне не пригодилась. Мне всё-таки кажется, что это всё мертворождённо. На современных многоядерных процессорах можно не изобретать псевдо-потоки,
Ш>а проще и выгодней пользоваться настоящей многопоточностью с настоящим параллелизмом.

В настоящей многопоточности нужна синхронизация, а в корутинах с этим все проще.
Так что если задача позволяет — часто корутины удобнее...
Re: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Abyx Россия  
Дата: 04.07.13 08:57
Оценка: -1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Эмуляция оператора await из языка C# 5.

EP>Данный proof-of-concept показывает, что идентичный синтаксис оператора await может быть достигнут с помощью Stackful Coroutines, демонстрируя что они предоставляют превосходящие возможности.
EP>Цель данного proof-of-concept — привлечь внимание к Stackful Coroutines, а не эмуляция await'а сама по себе — так как с помощью сопроцедур можно достичь более высоких уровней инкапсуляции
Автор: Evgeny.Panasyuk
Дата: 21.06.13
.


у Stackful Coroutines есть фатальный недостаток — они Stackful, и это значит нельзя сделать 10К сoroutines.
т.е. если ты пишешь сетевой сервер, ты не можешь использовать архитектуру "сопрограмма на клиент".
In Zen We Trust
Re[2]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 04.07.13 10:35
Оценка: 3 (1) +1
Здравствуйте, Abyx, Вы писали:

A>у Stackful Coroutines есть фатальный недостаток — они Stackful, и это значит нельзя сделать 10К сoroutines.

A>т.е. если ты пишешь сетевой сервер, ты не можешь использовать архитектуру "сопрограмма на клиент".

Я делал тест 200k корутин (Boost.Coroutine) — полёт нормальный. Из дополнительных настроек уменьшил default размер стэка (задаётся в конструкторе).
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Шахтер Интернет  
Дата: 04.07.13 15:49
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Добавить в стандарт можно, но не корутины сами по себе, а определённый набор функций для управления контекстом. Остальное можно построить на их основе разными способами.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Шахтер Интернет  
Дата: 04.07.13 15:53
Оценка:
Здравствуйте, enji, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>Здравствуйте, Evgeny.Panasyuk, Вы писали:


Ш>>Я вот лет 10 назад экспериментировал с корутинами. Сделал реализацию под студию. Насколько я понимаю, аналогичная реализация сейчас добавлена в boost.

Ш>>И так с тех пор она мне не пригодилась. Мне всё-таки кажется, что это всё мертворождённо. На современных многоядерных процессорах можно не изобретать псевдо-потоки,
Ш>>а проще и выгодней пользоваться настоящей многопоточностью с настоящим параллелизмом.

E>В настоящей многопоточности нужна синхронизация, а в корутинах с этим все проще.


Есть такое. Просто корутины передают управление в фиксированных точках, что упрощает многие вещи.

E>Так что если задача позволяет — часто корутины удобнее...


Зато потоки обеспечат выигрыш в производительности.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: enji  
Дата: 04.07.13 16:26
Оценка:
Здравствуйте, Шахтер, Вы писали:

E>>Так что если задача позволяет — часто корутины удобнее...


Ш>Зато потоки обеспечат выигрыш в производительности.


С этим я не спорю
Лично у меня специфика такова, что задачи зависят в основном от скорости обмена по сети или по последовательному порту. А для таких случаев удобно большую часть задач крутить в одном потоке, а чтобы писать нормальный код в таком стиле и используются корутины.
Re: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: night beast СССР  
Дата: 05.07.13 17:29
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Эмуляция оператора await из языка C# 5.

EP>Данный proof-of-concept показывает, что идентичный синтаксис оператора await может быть достигнут с помощью Stackful Coroutines, демонстрируя что они предоставляют превосходящие возможности.
EP>Цель данного proof-of-concept — привлечь внимание к Stackful Coroutines, а не эмуляция await'а сама по себе — так как с помощью сопроцедур можно достичь более высоких уровней инкапсуляции
Автор: Evgeny.Panasyuk
Дата: 21.06.13
.


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

Re[2]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 05:37
Оценка: +1
Здравствуйте, night beast, Вы писали:

NB>честно говоря, поражаюсь вашему терпению.

NB>сам бы уже несколько раз бросил что-либо доказывать упертым шарперам
NB>

Не, это совсем не из-за "упёртых шарперов" — я в той теме даже не показывал
Я сделал этот прототип, сразу после того как посмотрел презентацию Саттера. Он рассказал, о том, что возможно в C++ добавят await. Я же предпочту сначала увидеть Stackful Coroutines в ISO, так как они более мощные, поэтому и сделал пример.
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 04.10.13 17:58
Оценка: 61 (7)
EP>Я сделал этот прототип, сразу после того как посмотрел презентацию Саттера. Он рассказал, о том, что возможно в C++ добавят await. Я же предпочту сначала увидеть Stackful Coroutines в ISO, так как они более мощные, поэтому и сделал пример.

Этот прототип теперь используется в N3708 "A proposal to add coroutines to the C++ standard library" как пример (page 5)
Re[4]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: koodeer  
Дата: 04.10.13 20:12
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Добавить в стандарт можно, но не корутины сами по себе, а определённый набор функций для управления контекстом. Остальное можно построить на их основе разными способами.


Это является и достоинством, и недостатком одновременно. Тем и плох C++, что почти всё можно сделать слишком большим количество разных способов. Это усложняет поддержку проектов, усложняет вхождение в проект новых людей.
Вон в C# способов раз-два и обчёлся. Зато даже джуниоры знают (ну или считают, что знают) async/await.
Re[5]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: jazzer Россия Skype: enerjazzer
Дата: 04.10.13 20:27
Оценка:
Здравствуйте, koodeer, Вы писали:

K>Здравствуйте, Шахтер, Вы писали:


Ш>>Добавить в стандарт можно, но не корутины сами по себе, а определённый набор функций для управления контекстом. Остальное можно построить на их основе разными способами.


K>Это является и достоинством, и недостатком одновременно. Тем и плох C++, что почти всё можно сделать слишком большим количество разных способов. Это усложняет поддержку проектов, усложняет вхождение в проект новых людей.

K>Вон в C# способов раз-два и обчёлся. Зато даже джуниоры знают (ну или считают, что знают) async/await.

Ну так С++ и не позиционировался никогда как дружественный к новичкам. У него несколько другие приоритеты
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: zaufi Земля  
Дата: 04.10.13 20:29
Оценка:
Здравствуйте, koodeer, Вы писали:

K>Здравствуйте, Шахтер, Вы писали:


Ш>>Добавить в стандарт можно, но не корутины сами по себе, а определённый набор функций для управления контекстом. Остальное можно построить на их основе разными способами.


K>Это является и достоинством, и недостатком одновременно. Тем и плох C++, что почти всё можно сделать слишком большим количество разных способов. Это усложняет поддержку проектов, усложняет вхождение в проект новых людей.


что-то на вхождение в Perl или там Python это не особо влияет я смотрю %) да и жалоб со от разработчиков что-то не слышно (в основном "нытье" от тех кто изучает).
Perl я могу читать только простой код, а вот на Python доводилось кодить разного... по количеству способов сделать одно и тоже С++ до него как ... ну вы поняли...

K>Вон в C# способов раз-два и обчёлся. Зато даже джуниоры знают (ну или считают, что знают) async/await.
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.10.13 20:48
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

A>>у Stackful Coroutines есть фатальный недостаток — они Stackful, и это значит нельзя сделать 10К сoroutines.

A>>т.е. если ты пишешь сетевой сервер, ты не можешь использовать архитектуру "сопрограмма на клиент".

EP>Я делал тест 200k корутин (Boost.Coroutine) — полёт нормальный. Из дополнительных настроек уменьшил default размер стэка (задаётся в конструкторе).


200К которые счетчик инкрементили или это был сервер простецкий ?
Re[6]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: jazzer Россия Skype: enerjazzer
Дата: 04.10.13 20:50
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>что-то на вхождение в Perl или там Python это не особо влияет я смотрю %) да и жалоб со от разработчиков что-то не слышно (в основном "нытье" от тех кто изучает).

Z>Perl я могу читать только простой код, а вот на Python доводилось кодить разного... по количеству способов сделать одно и тоже С++ до него как ... ну вы поняли...

И это при том, что Питон именно в этом

There should be one — and preferably only one — obvious way to do it.

объявил священную войну Перлу,
  который на самом деле проповедует вот что

Just because you CAN do something a particular way doesn't mean that you SHOULD do it that way. Perl is designed to give you several ways to do anything, so consider picking the most readable one.


но кого это волнует


ЗюЫю Кстати, я недавно натолкнулся на явную поддержку в Перле оптимизации хвостовой рекурсии — был приятно удивлен
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.10.13 21:05
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, night beast, Вы писали:


NB>>честно говоря, поражаюсь вашему терпению.

NB>>сам бы уже несколько раз бросил что-либо доказывать упертым шарперам
NB>>

EP>Не, это совсем не из-за "упёртых шарперов" — я в той теме даже не показывал

EP>Я сделал этот прототип, сразу после того как посмотрел презентацию Саттера. Он рассказал, о том, что возможно в C++ добавят await. Я же предпочту сначала увидеть Stackful Coroutines в ISO, так как они более мощные, поэтому и сделал пример.

Stackfull точно не будет. Судя по голосовалке на этом сайте файберы использовало ажно 7% программистов и это при том, что голосовалка была создана ажно в 2005м, когда местные сиплюсники еще боялись признаться, что они уже дотнетчики
Re[4]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 05.10.13 12:14
Оценка:
Здравствуйте, Ikemefula, Вы писали:

A>>>у Stackful Coroutines есть фатальный недостаток — они Stackful, и это значит нельзя сделать 10К сoroutines.

A>>>т.е. если ты пишешь сетевой сервер, ты не можешь использовать архитектуру "сопрограмма на клиент".
EP>>Я делал тест 200k корутин (Boost.Coroutine) — полёт нормальный. Из дополнительных настроек уменьшил default размер стэка (задаётся в конструкторе).
I>200К которые счетчик инкрементили или это был сервер простецкий ?

while(true)
{
    ++counter;
    yield();
}
Re[4]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 05.10.13 12:23
Оценка:
I>Stackfull точно не будет.

Не вижу принципиальных преград. Например в D есть fiber'ы.

I>Судя по голосовалке на этом сайте файберы использовало ажно 7% программистов


7% от чего? Какой вопрос был?
Я, например, сильно сомневаюсь что хотя бы 7% от всех C#'еров использует await, или даже yield.
Re[5]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.10.13 15:19
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Не вижу принципиальных преград. Например в D есть fiber'ы.


Основная преграда это востребованность.

I>>Судя по голосовалке на этом сайте файберы использовало ажно 7% программистов


EP>7% от чего? Какой вопрос был?


Вопрос простой — использовали ли вы файберы. Проголосовало достаточно большое количество людей, что бы делать какие то выводы.

EP>Я, например, сильно сомневаюсь что хотя бы 7% от всех C#'еров использует await, или даже yield.


Гораздо больше. Асинхронщина нужна и часто апи даже не подразумевает синхронных вызовов. Колбеки, rx, tpl — всё намного сложнее, чем авайт.
Re[6]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 05.10.13 16:01
Оценка:
Здравствуйте, Ikemefula, Вы писали:

EP>>Не вижу принципиальных преград. Например в D есть fiber'ы.

I>Основная преграда это востребованность.
I>>>Судя по голосовалке на этом сайте файберы использовало ажно 7% программистов
EP>>7% от чего? Какой вопрос был?
I>Вопрос простой — использовали ли вы файберы. Проголосовало достаточно большое количество людей, что бы делать какие то выводы.

IMHO — если 7% реально использовало, то это даже хорошая востребованность
А если учесть то, что появилась реально удобная и кросс-платформенная реализация, причём на самом видном месте — то процент будет только расти.

EP>>Я, например, сильно сомневаюсь что хотя бы 7% от всех C#'еров использует await, или даже yield.

I>Гораздо больше.

Не верю. await появился чуть больше года назад, я сомневаюсь что на VS2012 перешло много контор.
Re[7]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 05.10.13 17:35
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>IMHO — если 7% реально использовало, то это даже хорошая востребованность

EP>А если учесть то, что появилась реально удобная и кросс-платформенная реализация, причём на самом видном месте — то процент будет только расти.

Сильно вряд ли. Основной тренд это мощные локальные фичи, навроде авайта. Основная проблема не в синтексисе и удобстве а в сложности самой концепции — кооперативной многозадачности.

EP>>>Я, например, сильно сомневаюсь что хотя бы 7% от всех C#'еров использует await, или даже yield.

I>>Гораздо больше.

EP>Не верю. await появился чуть больше года назад, я сомневаюсь что на VS2012 перешло много контор.


Нет особых проблем в переходе на нужный фремворк, обратная совместимость почти идеальная. Авайт очень сильно облегчает работу и позволяет убрать вагоны кода.
Re[8]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 05.10.13 18:28
Оценка:
Здравствуйте, Ikemefula, Вы писали:

EP>>IMHO — если 7% реально использовало, то это даже хорошая востребованность

EP>>А если учесть то, что появилась реально удобная и кросс-платформенная реализация, причём на самом видном месте — то процент будет только расти.
I>Сильно вряд ли.

Согласен, но раза в 1.5 — спокойно.

I>Основной тренд это мощные локальные фичи, навроде авайта.


await и yield — это реально удобные feature, и у них очень много общего.
Нужно пытаться их обобщать — в духе C++ вводить features, которые не ограниченны несколькими конкретными применениями. Также library-only feature предпочтительней чем требующие изменения в самом языке. И один из вариантов это stackful coroutine — на основе которой реализуются и await, и yield, и многие другие features, которая реализуется как library-only.

I>Основная проблема не в синтексисе и удобстве а в сложности самой концепции — кооперативной многозадачности.


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

I>Авайт очень сильно облегчает работу и позволяет убрать вагоны кода.


Согласен, но это не означет что все C#'исты кинулись его изучать. Многие годами ничего не изучают, не следят за новыми фичами и т.п. И как-то не верится в то, что "гораздо больше 7% C#'еров используют годовалую фичу".
Re[8]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Jack128  
Дата: 05.10.13 19:49
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Нет особых проблем в переходе на нужный фремворк, обратная совместимость почти идеальная.

наверно из-за идеальной совместимости тут, на рсдн, появляются темы какого гуя у мя в 4,0 работает, а в 4,5 не работает..
Re[9]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.10.13 09:18
Оценка:
Здравствуйте, Jack128, Вы писали:

I>>Нет особых проблем в переходе на нужный фремворк, обратная совместимость почти идеальная.

J>наверно из-за идеальной совместимости тут, на рсдн, появляются темы какого гуя у мя в 4,0 работает, а в 4,5 не работает..

Слово "почти" перевести что ли ?
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 28.11.13 20:57
Оценка:
Здравствуйте, enji, Вы писали:

E>В настоящей многопоточности нужна синхронизация, а в корутинах с этим все проще.

E>Так что если задача позволяет — часто корутины удобнее...

Здесь она тоже нужна, просто ты можешь вместо синхронизации — переключать нужным образом корутины. Но эти самые корутины тоже могут изменять общие данные. Настоящие потоки, кстати, имеют очень много приятных свойств, например, планировщик ОС пытается предотвращать starvation и priority inversion, планировщик меняет приоритеты потоков динамически, снижая приоритет CPU bound потоков и повышая приоритет I/O bound потоков, для того, чтобы повысить отзывчивость системы. В общем, когда люди берутся писать код на корутинах или асинхронный код на boost.asio — они часто впервые в жизни сталкиваются со всеми этими проблемами
Re[3]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 28.11.13 21:09
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Я делал тест 200k корутин (Boost.Coroutine) — полёт нормальный. Из дополнительных настроек уменьшил default размер стэка (задаётся в конструкторе).


ОС?
Re[4]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 28.11.13 21:47
Оценка:
Здравствуйте, Lazin, Вы писали:

EP>>Я делал тест 200k корутин (Boost.Coroutine) — полёт нормальный. Из дополнительных настроек уменьшил default размер стэка (задаётся в конструкторе).

L>ОС?

Windows 7 x64, MSVC2010SP1 x64, Boost 1.53. Должно работать и на других OS, но не проверял.
Re[5]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 29.11.13 08:13
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали

EP>Windows 7 x64, MSVC2010SP1 x64, Boost 1.53. Должно работать и на других OS, но не проверял.


А сколько на той машине памяти и свопа и какой размер стока пришлось поставить?
Re[6]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 29.11.13 11:48
Оценка:
Здравствуйте, Lazin, Вы писали:

EP>>Windows 7 x64, MSVC2010SP1 x64, Boost 1.53. Должно работать и на других OS, но не проверял.

L>А сколько на той машине памяти и свопа и какой размер стока пришлось поставить?

Памяти 6GiB, свопа нет. Размер стэка 10KiB.
#include <boost/container/vector.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/coroutine/all.hpp>
#include <exception>
#include <iostream>

using namespace boost;
using namespace std;

unsigned long counter = 0;

int main()
try
{
    const auto n = 200000;
    const auto stack = 10 * (1u<<10);

    typedef coroutines::coroutine< void() > Coro;
    container::vector<Coro> fibers;
    fibers.reserve(n);
    for(auto i=0; i!=n; ++i)
    {
        fibers.emplace_back([](Coro::caller_type &yield)
        {
            while(true)
            {
                ++counter;
                yield();
            }
        }, coroutines::attributes(stack));
    }

    while(true)
    {
        for_each(fibers, [](Coro &yield)
        {
            yield();
        });
        cout << counter << endl;
    }
}
catch(const std::exception &e)
{
    cout << e.what() << endl;
}
Но там ещё много других настроек, например нужно ли сохранять fpu регистры и т.п. 200k это не предел, например только изменив стэк на 1KiB получилось сходу запустить 400k корутин.
Re[7]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 29.11.13 22:23
Оценка: 21 (1)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Памяти 6GiB, свопа нет. Размер стэка 10KiB.


И всего 200К корутин
Фишка async в F#/C# в том, что можно особо не думать о ресурсах, просто запускать таск на каждый чих и все будет хорошо. Это делает возможным несколько иной стиль программирования. Допустим нам нужно обработать каждый файл в директории, рекурсивно, просто запускаем таск на каждый файл или директорию, а пулл потоков будет их постепенно выполнять, пока они не закончатся. Причем таски в C# могут порождать другие таски и зависеть друг от друга. А под капотом там task stealing планировщик, как в Cilk. В boost.coroutine же нет никакого планировщика, AFAIK. В общем, на мой взгляд их не очень корректно сравнивать.

Также стоит обратить внимание на то, что ограничением в этом эксперименте является количество вирт. памяти, выделенной под стек, не количество физической памяти (там скорее всего выделяется по одной странице физ. памяти на стек). В винде есть глобальное ограничение на количество выделенной виртуальной памяти для всех процессов — commit limit. По умолчанию commit limit = размер своп файла + общий объем физичской памяти — некоторое заранее неизвестное количество памяти под нужны системы. Если процесс вылез за commit limit — он получит ООМ, даже если свободной физической памяти много. Это называется overcommit и в винде он, AFAIK, запрещен. Может быть его можно как-то разрешить, я не знаю. В linux overcommit по умолчанию разрешен, но там есть эвристический алгоритм, который может прибить процесс, ушедший в overcommit. Также, overcommit там может быть разрешен полностью или запрещен как в винде настройками. В общем, виртуальное адресное пространство — вещь не бесконечная и может быть исчерпано очень быстро. Это несколько ограничивает применимость подобных корутин на практике.
Re[8]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 29.11.13 22:58
Оценка:
Здравствуйте, Lazin, Вы писали:

EP>>Памяти 6GiB, свопа нет. Размер стэка 10KiB.

L>И всего 200К корутин

Я уверен что можно и больше — но нужно играться с настройками, сейчас мне это не настолько интересно.

L>Фишка async в F#/C# в том, что можно особо не думать о ресурсах, просто запускать таск на каждый чих и все будет хорошо.


У stackless корутин безусловно есть свою плюсы. Вот тут описывал
Автор: Evgeny.Panasyuk
Дата: 19.11.13
некоторые пункты.
И сейчас stackless корутины доступны для C++, только в весьма ограниченном виде (я даже как-то делал мини реализацию await в таком stackless стиле).

L>А под капотом там task stealing планировщик, как в Cilk. В boost.coroutine же нет никакого планировщика, AFAIK. В общем, на мой взгляд их не очень корректно сравнивать.


Планировщик это вообще ортогональная вещь.
await умеет работать с разными планировщиками, syncronization и execution контексты (или как-то так) — настраиваемые. Он может работать и с самодельным пулом потоков и с чем-то на подобие Boost.Asio в одном потоке. Точно также и корутины могут работать с разными планировщиками — можно с Asio использовать, а можно например с GUI Message Loop.

L>В общем, виртуальное адресное пространство — вещь не бесконечная и может быть исчерпано очень быстро. Это несколько ограничивает применимость подобных корутин на практике.


У них аллокатор стэка настраивается.
Если нужна куча долгоживущих корутин — то достаточно применить простеший аллокатор, который съест большой блок, и для аллокации просто будет делать free += requested;
Re[8]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: alex_public  
Дата: 30.11.13 00:13
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Фишка async в F#/C# в том, что можно особо не думать о ресурсах, просто запускать таск на каждый чих и все будет хорошо.


Обожаю эти фразы в стиле C#/Java.

L>Это делает возможным несколько иной стиль программирования. Допустим нам нужно обработать каждый файл в директории, рекурсивно, просто запускаем таск на каждый файл или директорию, а пулл потоков будет их постепенно выполнять, пока они не закончатся. Причем таски в C# могут порождать другие таски и зависеть друг от друга. А под капотом там task stealing планировщик, как в Cilk. В boost.coroutine же нет никакого планировщика, AFAIK. В общем, на мой взгляд их не очень корректно сравнивать.


Единственное преимущество .net в данном случае — это единство синтаксиса. Т.е. запись при просто асинхронной работе или при пуле потоков и т.п. выглядит практически одинаково. А в C++ это вообще отдельные сущности. Т.е. хочется асинхронности — ставим одну библиотеку, хочется пул потоков — ставим другую, хочется одно поверх другого — сопрягаем их вместе. Естественно при этом даётся больше возможностей, чем в .net варианте, но и единого универсального синтаксиса естественно нет. Какой вариант лучше, думаю дело личных вкусов и стилей...

L>Также стоит обратить внимание на то, что ограничением в этом эксперименте является количество вирт. памяти, выделенной под стек, не количество физической памяти (там скорее всего выделяется по одной странице физ. памяти на стек). В винде есть глобальное ограничение на количество выделенной виртуальной памяти для всех процессов — commit limit. По умолчанию commit limit = размер своп файла + общий объем физичской памяти — некоторое заранее неизвестное количество памяти под нужны системы. Если процесс вылез за commit limit — он получит ООМ, даже если свободной физической памяти много. Это называется overcommit и в винде он, AFAIK, запрещен. Может быть его можно как-то разрешить, я не знаю. В linux overcommit по умолчанию разрешен, но там есть эвристический алгоритм, который может прибить процесс, ушедший в overcommit. Также, overcommit там может быть разрешен полностью или запрещен как в винде настройками. В общем, виртуальное адресное пространство — вещь не бесконечная и может быть исчерпано очень быстро. Это несколько ограничивает применимость подобных корутин на практике.


На практике? ) Вышеописанное соответствует очень узкой категории задач, типа написания высоконагруженного сервера на множество клиентов. И для таких задач есть свой набор известных по этой области решений.
Re[8]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Cyberax Марс  
Дата: 30.11.13 00:19
Оценка:
Здравствуйте, Lazin, Вы писали:

L> В linux overcommit по умолчанию разрешен, но там есть эвристический алгоритм, который может прибить процесс, ушедший в overcommit.

Не будет. Пока процесс не начнёт трогать страницы — можно хоть 100Гб распределять.
cyberax@virtlin:~$ cat test.c 
#include <stdio.h>
#include <malloc.h>

int main()
{
    void * ptr = malloc(1024LL*1024*1024*60);
    if (ptr)
        printf("OK\n");
}
cyberax@virtlin:~$ gcc test.c 
cyberax@virtlin:~$ ./a.out 
OK
cyberax@virtlin:~$ free -m
             total       used       free     shared    buffers     cached
Mem:          4606       1999       2607          0        614        887
-/+ buffers/cache:        497       4108
Swap:         4765         12       4753
Sapienti sat!
Re[9]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 30.11.13 00:29
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>Памяти 6GiB, свопа нет. Размер стэка 10KiB.

L>>И всего 200К корутин
EP>Я уверен что можно и больше — но нужно играться с настройками, сейчас мне это не настолько интересно.
[...]
L>>В общем, виртуальное адресное пространство — вещь не бесконечная и может быть исчерпано очень быстро. Это несколько ограничивает применимость подобных корутин на практике.
EP>У них аллокатор стэка настраивается.
EP>Если нужна куча долгоживущих корутин — то достаточно применить простеший аллокатор, который съест большой блок, и для аллокации просто будет делать free += requested;

Собственно тест на таком простом аллокатаре выдаёт 400k корутин по 10KiB стэка (~3.8GiB только под стэки). Всего на систему памяти 6GiB, без swap (всякие фоновые программы работают и т.п.):
#include <boost/container/vector.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/coroutine/all.hpp>
#include <exception>
#include <iostream>

using namespace boost;
using namespace std;

container::vector<char> memory(size_t(1) << 32);
auto last_free = memory.data();

struct stack_allocator
{
    void *allocate(size_t size) const
    {
        return last_free += size;
    }
    void deallocate(void * vp, size_t size) const {}
};

unsigned long counter = 0;

int main()
try
{
    const auto n = 400000;
    const auto stack = 10 * (1u<<10);

    typedef coroutines::coroutine< void() > Coro;
    container::vector<Coro> fibers;
    fibers.reserve(n);
    for(auto i=0; i!=n; ++i)
    {
        fibers.emplace_back([](Coro::caller_type &yield)
        {
            while(true)
            {
                ++counter;
                yield();
            }
        }, coroutines::attributes(stack), stack_allocator());
    }
    cout << "allocated for stacks: " << (last_free - memory.data())/(1u << 20) << endl;

    while(true)
    {
        for_each(fibers, [](Coro &yield)
        {
            yield();
        });
        cout << counter << endl;
    }
}
catch(const std::exception &e)
{
    cout << e.what() << endl;
}
При желании можно ещё больше выжать.
Re[8]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 30.11.13 00:51
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Также стоит обратить внимание на то, что ограничением в этом эксперименте является количество вирт. памяти, выделенной под стек, не количество физической памяти (там скорее всего выделяется по одной странице физ. памяти на стек). В винде есть глобальное ограничение на количество выделенной виртуальной памяти для всех процессов — commit limit. По умолчанию commit limit = размер своп файла + общий объем физичской памяти — некоторое заранее неизвестное количество памяти под нужны системы. Если процесс вылез за commit limit — он получит ООМ, даже если свободной физической памяти много. Это называется overcommit и в винде он, AFAIK, запрещен. Может быть его можно как-то разрешить, я не знаю.


#include <Windows.h>
#include <iostream>
#include <cstddef>

int main()
{    
    using namespace std;

    for(auto i=0; i!=32; ++i)
        cout << VirtualAlloc(0, size_t(1) << 36, MEM_RESERVE, PAGE_READWRITE) << endl;
}

000000013FCF0000
000000113FCF0000
000000213FCF0000
000000313FCF0000
000000413FCF0000
000000513FCF0000
000000613FCF0000
000000713FCF0000
000000813FCF0000
000000913FCF0000
000000A13FCF0000
000000B13FCF0000
000000C13FCF0000
000000D13FCF0000
000000E13FCF0000
000000F13FCF0000
000001013FCF0000
000001113FCF0000
000001213FCF0000
000001313FCF0000
000001413FCF0000
000001513FCF0000
000001613FCF0000
000001713FCF0000
000001813FCF0000
000001913FCF0000
000001A13FCF0000
000001B13FCF0000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
Никаких настроек не менял
Re[9]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.11.13 08:57
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Lazin, Вы писали:


EP>>>Памяти 6GiB, свопа нет. Размер стэка 10KiB.

L>>И всего 200К корутин

EP>Я уверен что можно и больше — но нужно играться с настройками, сейчас мне это не настолько интересно.

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

EP>У stackless корутин безусловно есть свою плюсы. Вот тут описывал
Автор: Evgeny.Panasyuk
Дата: 19.11.13
некоторые пункты.

EP>И сейчас stackless корутины доступны для C++, только в весьма ограниченном виде (я даже как-то делал мини реализацию await в таком stackless стиле).

Я не утверждаю что оно не нужно, просто у корутин и async/await несколько разные потенциальные области применения. Посему поддержка async/await в стандарте это гуд, независимо от того, есть ли корутины в стандартной библиотеке или нет.
Re[9]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.11.13 09:02
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>
EP>#include <Windows.h>
EP>#include <iostream>
EP>#include <cstddef>

EP>int main()
EP>{    
EP>    using namespace std;

EP>    for(auto i=0; i!=32; ++i)
EP>        cout << VirtualAlloc(0, size_t(1) << 36, MEM_RESERVE, PAGE_READWRITE) << endl;
EP>}
EP>

EP>
EP>000000013FCF0000
EP>000000113FCF0000
EP>000000213FCF0000
EP>000000313FCF0000
EP>000000413FCF0000
EP>000000513FCF0000
EP>000000613FCF0000
EP>000000713FCF0000
EP>000000813FCF0000
EP>000000913FCF0000
EP>000000A13FCF0000
EP>000000B13FCF0000
EP>000000C13FCF0000
EP>000000D13FCF0000
EP>000000E13FCF0000
EP>000000F13FCF0000
EP>000001013FCF0000
EP>000001113FCF0000
EP>000001213FCF0000
EP>000001313FCF0000
EP>000001413FCF0000
EP>000001513FCF0000
EP>000001613FCF0000
EP>000001713FCF0000
EP>000001813FCF0000
EP>000001913FCF0000
EP>000001A13FCF0000
EP>000001B13FCF0000
EP>0000000000000000
EP>0000000000000000
EP>0000000000000000
EP>0000000000000000
EP>
Никаких настроек не менял


Ну я пару лент назад пытался переписать кое что на файберы, тогда еще не было boost.coroutine, поэтому все строилось на Win32 API. User mode scheduling в винде тогда тоже еще не было. В общем, я именно с этим ограничением и столкнулся. Мне не удавалось создать больше чем swap size + physical memory size стеков. С помощью изменения размера стека мне удалось запустить больше файберов, но все равно этого не хватало, поэтому пришлось продолжить использовать event based архитектуру. Потом я прочитал у Русиновича о том, что каждой странице вирт. памяти в винде должна быть сопоставлена либо страница физической памяти, либо страница в page-файле.
Re[9]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.11.13 09:04
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Lazin, Вы писали:


L>> В linux overcommit по умолчанию разрешен, но там есть эвристический алгоритм, который может прибить процесс, ушедший в overcommit.

C>Не будет. Пока процесс не начнёт трогать страницы — можно хоть 100Гб распределять.

Мой поинт не в том, что нельзя, а в том, что такой подход не универсален, так как требует чтобы система была настроена определенным образом, а в linux можно запретить overcommit, насколько я знаю.
Re[9]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.11.13 09:10
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Обожаю эти фразы в стиле C#/Java.

Я тоже, от того и использую :P
Вообще, async/await в C# появились после continuation expressions в F# и авторы первого не скрывали, что именно послужило прообразом asyc/await.

_>Единственное преимущество .net в данном случае — это единство синтаксиса. Т.е. запись при просто асинхронной работе или при пуле потоков и т.п. выглядит практически одинаково. А в C++ это вообще отдельные сущности. Т.е. хочется асинхронности — ставим одну библиотеку, хочется пул потоков — ставим другую, хочется одно поверх другого — сопрягаем их вместе. Естественно при этом даётся больше возможностей, чем в .net варианте, но и единого универсального синтаксиса естественно нет. Какой вариант лучше, думаю дело личных вкусов и стилей...

Я тут не пытаюсь доказывать преимущество .NET. Если хотелось поспорить с кем нибудь на эту тему, то я ничем не могу помочь, давно ничего под .NET не писал, а async/await никогда не использовал на практике.

_>На практике? ) Вышеописанное соответствует очень узкой категории задач, типа написания высоконагруженного сервера на множество клиентов. И для таких задач есть свой набор известных по этой области решений.

Обожаю фразу "высоконагруженные сервера"
Если по делу, то расскажите об этом разработчикам, использующим Cilk, пусть они перестанут использовать spawn для распараллеливания всяких там сортировок
Re[10]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 30.11.13 09:22
Оценка:
Здравствуйте, Lazin, Вы писали:

EP>>Я уверен что можно и больше — но нужно играться с настройками, сейчас мне это не настолько интересно.

L>Можно и больше, но это чревато проблемами если из корутины вызывается thrid party код, который использует слишком много стека.

1. Сотни тысяч корутин нужны крайне редко.
2. Проблема сглаживается поддержкой segmented stacks.

L>Я не утверждаю что оно не нужно, просто у корутин и async/await несколько разные потенциальные области применения. Посему поддержка async/await в стандарте это гуд, независимо от того, есть ли корутины в стандартной библиотеке или нет.


Есть stackful и stackless корутины, и там и там есть свои уникальные плюсы. Поверх корутин реализуется и await, и yield (в C# и то и то реализуется поверх stackless корутин) — не вижу смысла добавлять только await в ISO, когда можно добавить более общий механизм.
Re[10]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Evgeny.Panasyuk Россия  
Дата: 30.11.13 09:33
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Потом я прочитал у Русиновича о том, что каждой странице вирт. памяти в винде должна быть сопоставлена либо страница физической памяти, либо страница в page-файле.


Там скорей всего говорилось про committed memory.
Re[10]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: alex_public  
Дата: 30.11.13 12:39
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Я тоже, от того и использую :P

L>Вообще, async/await в C# появились после continuation expressions в F# и авторы первого не скрывали, что именно послужило прообразом asyc/await.

F# интересный, да... Там привносящиеся .net'ом минусы, хотя бы компенсируются добавляемыми фичами языка.

L>Я тут не пытаюсь доказывать преимущество .NET. Если хотелось поспорить с кем нибудь на эту тему, то я ничем не могу помочь, давно ничего под .NET не писал, а async/await никогда не использовал на практике.


Не не, я тут уже наспорился с дотнетчиками — больше нет никакого желания. Они в большинстве своём какие-то тупо непробиваемые. ))) Просто тут же было прямое сравнение между сопроцедурами из буста и await/async, вот я и высказался...

L>Обожаю фразу "высоконагруженные сервера"

L>Если по делу, то расскажите об этом разработчикам, использующим Cilk, пусть они перестанут использовать spawn для распараллеливания всяких там сортировок

Ха, так и я о том же. Что в большинстве задач требуется именно многопоточное программирование. Которое почти всегда удобнее и эффективнее. И кстати для него вообще не нужные никакие await/async или сопроцедуры. Единственная ситуация, когда оно не применимо, это как раз те самые высоконагруженные сервера, потому как в таком случае расход памяти и накладные расходы на переключение контекста становятся слишком высокими. В таком случае применяют какой-то вид асинхронного программирования (и кстати это всё ещё не await/async или сопроцедуры), которое весьма не удобно в программирование, но зато эффективно в данном случае. И вот только теперь у нас ещё дополнительно могут возникнуть сопроцедуры (или await/async) — они позволяют записать наш кривой асинхронный код в таком виде, как будто бы это обычное многопоточное программирование.

Конечно сопроцедуры или await/async могут принести немного пользы и в этом самом обычном многопоточном программирование... Но очень небольшую — исполняя всего лишь роль синтаксического сахара для записи "продолжений". Причём например лично мне это не особо нравится, т.к. на мой взгляд только запутывает код. Мне больше нравится реализовывать многопоточность явной записью и реализуя что-то типа модели акторов.

А так вообще с классической многопоточностью в C++ мне кажется всё нормально уже сейчас. Есть ручные потоки (удобный класс thread и много мелочей вокруг этого), есть пулы потоков (boost:threadpool какой-нибудь), есть автоматическое распараллеливание для алгоритмов (openmp). Это не говоря уже о нескольких монструозных библиотеках (типа tbb), в которых есть сразу всё и ещё куча всего. ))) Единственно, чего на мой взгляд не хватает для многопоточности в C++, это как раз стандартной готовой реализации модели акторов. Есть конечно какие-то там libcppa, theron и т.п., но это всё не то. Кстати, а вот в D подобное реализовано на полную в стандартной библиотеке, причём, благодаря возможностям языка, на базе удобного "сопоставления с образцом".
Re[11]: [trick] await in C++ based on Stackful Coroutines from Boost.Coroutine
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.11.13 20:56
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Lazin, Вы писали:


L>>Потом я прочитал у Русиновича о том, что каждой странице вирт. памяти в винде должна быть сопоставлена либо страница физической памяти, либо страница в page-файле.


EP>Там скорей всего говорилось про committed memory.


Действительно, речь там кажется шла о commited memory Тогда да, проблема запуска 100500 корутин должна легко решаться всякими хитрыми алокаторами.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.