vak: (Default)
Serge Vakulenko ([personal profile] vak) wrote2021-06-21 06:15 pm

48 байт на одну сопрограмму

Судя по комментам к предыдущему посту, существует устойчивое подозрение, что сопрограммы имеют стек, и вообще кушают ресурсы. Хорошо, давайте померяем, это нетрудно. Создадим миллион сопрограмм и глянем расход памяти. Вот такой тестик.
co_void_t print(int n)
{
for (;;) {
std::cout << n << std::endl;
co_await co_await_t{};
}
}

int main(int argc, char **argv)
{
std::coroutine_handle<> continuation[1000000];

std::cout << "Using " << mallinfo().uordblks << " bytes after start.\n";

for (int i = 0; i < 1000000; i++)
continuation[i] = print(i);

std::cout << "Using " << mallinfo().uordblks << " bytes after coroutine allocation.\n";

for (int i = 0; i < 1000000; i++)
continuation[i].resume();

std::cout << "Using " << mallinfo().uordblks << " bytes after coroutine run.\n";

for (int i = 0; i < 1000000; i++)
continuation[i].destroy();

std::cout << "Using " << mallinfo().uordblks << " bytes after coroutine destroyed.\n";
return 0;
}
Результат:
Using 77488 bytes after start.
Using 48077488 bytes after coroutine allocation.
0
...
999999
Using 48077488 bytes after coroutine run.
Using 77824 bytes after coroutine destroyed.
Делим разницу на количество сопрограмм: (48077488 - 77488) / 1000000 = 48 байтов на одну сопрограмму. Вполне недорогое удовольствие получается. Конечно, никакого собственного стека у сопрограмм не имеется, просто негде.
sab123: (Default)

[personal profile] sab123 2021-06-22 02:55 am (UTC)(link)
Стек сопрограмм выражается в виде контекстов, которые они аллокируют(как это по-русски?) из кучи. Это, кстати, и к вопросу об отладке: чтобы понять стек вызова, надо раскручивать цепочку этих контекстов.

В результате выгода в том, что пока сопрограмма активно не выполняется, ей не надо _пустое_место_ на стеке. И синхронные функции выполняются с той же эффективностью как обычно. А вот асинхронные функции (сопрограммы) имеют дополнительные накладные расходы по динамическому распределению памяти для стековых фреймов.
spamsink: (Default)

[personal profile] spamsink 2021-06-22 05:05 am (UTC)(link)
И что, если у сопрограммы есть локальные переменные, то они при каждом await/resume туда-сюда копируются? Если да, то это досадно.