История изменений
Исправление
Legioner,
(текущая версия)
:
У async/await есть небольшой, но оверхед
Давай сравнивать разные подходы.
Если мы используем потоки ОС, то в оверхед уходят:
-
Стеки потоков. Условно 8 МБ виртуальной памяти, используемая память с гранулярностью в условные 4 КБ. Т.е. если мой поток реально кушает 20 байтов на стеке и ему этого хватает, то всё равно ОС ему выделит 4 КБ. Также в оверхед уходит сохранение/восстановление кучи регистров и переключение между режимом пользователя и ядра. Это считается самым большим оверхедом.
-
Зелёные потоки, на примере Го. Со стеком тут всё примерно так же. Также глубокие стеки вызывают перерасход памяти, даже если они не используются. К примеру у нас энтерпрайз, и от начала потока до нашего реального метода проходит 500 вызовов всяких фреймворков. И в каждом потоке эти 500 вызовов будут дубликатами висеть и от этого никак не избавиться.
-
async/await. Тут перерасхода никакого по сути. Идёт замыкание исключительно с нужными данными, пара указателей. Задача может занимать считанные десятки байтов, вне зависимости от того, сколько вызовов было потрачено, пока к ней дошло управление.
-
Ручная state-машина. Ну по сути это самый оптимальный вариант. Причём async/await в идеале в неё и превращается.
Можно обвинять async/await в неудобной модели для программиста и я первый тут поддержу. Читать запутанный async/await-код может быть сложно. Научиться async/await ещё сложней. Лично я за зелёные потоки, как оптимальная середина - и для программиста всё просто как два рубля, и по производительности приемлемо. Но всё равно я считаю, что async/await (или на коллбеках алгоритмы) самые оптимальные по производительности. Хоть на удалённый сервер, хоть на локалхост, какая разница, всё равно тебе нужно организовывать управление соединениями.
Да не, это просто я недавно столкнулся с кодовой базой написанной в подобном стиле и до сих пор немного в шоке. Занимаюсь упрощением, потихоньку, чтоб любители сильно слоёной архитектуры, где IO засунуто в глубокие дали, да так, что не обмазавшись десятью моками ничего не оттестишь, не сразу заметили подвох.
Конечно лоб расшибить всегда можно. Но в любом случае твой вариант лучше, чем код-лапша, когда методы в сотни строк накопипасчены, что-то там рандомно меняется. Уж лучше паттерны.
Исходная версия
Legioner,
:
У async/await есть небольшой, но оверхед
Давай сравнивать разные подходы.
Если мы используем потоки ОС, то в оверхед уходят:
-
Стеки потоков. Условно 8 МБ виртуальной памяти, используемая память с гранулярностью в условные 4 КБ. Т.е. если мой поток реально кушает 20 байтов на стеке и ему этого хватает, то всё равно ОС ему выделит 4 КБ. Также в оверхед уходит сохранение/восстановление кучи регистров и переключение между режимом пользователя и ядра. Это считается самым большим оверхедом.
-
Зелёные потоки, на примере Го. Со стеком тут всё примерно так же. Также глубокие стеки вызывают перерасход памяти, даже если они не используются. К примеру у нас энтерпрайз, и от начала потока до нашего реального метода проходит 500 вызовов всяких фреймворков. И в каждом потоке эти 500 вызовов будут дубликатами висеть и от этого никак не избавиться.
-
async/await. Тут перерасхода никакого по сути. Идёт замыкание исключительно с нужными данными, пара указателей. Задача может занимать считанные десятки байтов, вне зависимости от того, сколько вызовов было потрачено, пока к ней дошло управление.
-
Ручная state-машина. Ну по сути это самый оптимальный вариант. Причём async/await в идеале в неё и превращается.
Можно обвинять async/await в неудобной модели для программиста и я первый тут поддержу. Читать запутанный async/await-код может быть сложно. Научиться async/await ещё сложней. Лично я за зелёные потоки, как оптимальная середина - и для программиста всё просто как два рубля, и по производительности приемлемо. Но всё равно я считаю, что async/await (или на коллбеках алгоритмы) самые оптимальные.
Да не, это просто я недавно столкнулся с кодовой базой написанной в подобном стиле и до сих пор немного в шоке. Занимаюсь упрощением, потихоньку, чтоб любители сильно слоёной архитектуры, где IO засунуто в глубокие дали, да так, что не обмазавшись десятью моками ничего не оттестишь, не сразу заметили подвох.
Конечно лоб расшибить всегда можно. Но в любом случае твой вариант лучше, чем код-лапша, когда методы в сотни строк накопипасчены, что-то там рандомно меняется. Уж лучше паттерны.