𝙽𝚒𝚌𝚔
Возьму нормальный сервер, заведу 10к потоков. В современном ядре idle потоки - очень дешёвая вещь. Если специфика задачи именно в минимальном латенси и 100к одновременных соединений, тогда да, событийная модель снизу доверху, epoll, event loop все дела
Маjко
Alexander
Я вот признаться не очень понимаю принципиальную разницу кто контекст переключает - сама прога или ядро за неё. Я сорян, теоретически как бы. Понятно что куча ньюансов в реальности .
Маjко
Если тебе нужно вертикальное масштабирование и высокий перформанс засчет более дорогой разработки (если мы не на го пишем) -- будь добр пиши asyncio
Маjко
Alexander
Опять же, сорян, теоретически , это проблемы системы. Запилите лёгкие корутины прямо в ядре :)
Маjко
Маjко
А чо, винде можно юзерспейсные приложения к ядру приколачивать же
Alexander
А запилили корутины в ядре и щапилите у них шареную память или типа того :)
Маjко
Чем мы хуже?)
Маjко
Alexander
Ну не вебсервис, а корутины
Alexander
Вот чел недавно на Хабре решил - надо веб-сокетам чтоб прямо в сетевую карту писал.
Маjко
Менять размер стека конкретного потока ты можешь, чем не корутины
Маjко
Контекстсвитч только никуда не денется
Чтобы убрать надо прямо в кернелспейсе гонять приложение, это дичь
Маjко
Ну не то чтобы костылить, rayon тебе и для потоков даст удобную абстракцию
𝙽𝚒𝚌𝚔
Сейчас попробовал выполнить ./lat_ctx -s 64 64 на ноуте (CPU 4ядра с гипертредингом), команда означает "контекст 64кб и 64 одновременных процесса", переключение контекста стоит 17.02 микросекунды. Думаю на серверном железе будет в районе 1мкс.
𝙽𝚒𝚌𝚔
это бенчмарк из lmbench
Маjко
Маjко
Ну и 64/64 это нифига не близко к реальности
Тогда уж замеряй 1мб/10k, речь то об этом
Маjко
𝙽𝚒𝚌𝚔
Знать бы как замерить... 1мб контекст - это явно чересчур, как правило это 2-3 указателя и некоторое кол-во локальных переменных
Маjко
Маjко
Ну да, может 1m и перебор, но с учетом того что стек не растет, придется пилить свой рантайм для управления лимитами
Маjко
Чтоб не проседать по памяти совсем уж
Alex
как компилятор раста компилит программу так чтобы не превысить максимальный размер стека?
Alex
на каждой системе свои лимиты же?
𝙽𝚒𝚌𝚔
Так, докину результаты ещё команды
/u/l/l/b/x86_64-linux-gnu ❯❯❯ ./lat_ctx -s 1024 -N 10 10 20 30 40 50 100 200 300 400 500 1000
"size=1024k ovr=43.47
10 135.71
20 142.00
30 143.59
40 142.51
50 142.63
100 142.38
200 140.07
300 143.99
400 141.29
500 143.14
1000 140.86
То есть с увеличением количества процессов стоимость переключения почти не увеличивается (растёт только потребление памяти естественно). И причём это настоящие живые одновременно работающие, для многих сетевых приложений такое наступает очень нескоро. Плюс, 1мб контекста - это прямо жир, хоть 140 мкс на переключение кажется многовато (на серверном железе можно ожидать раз в 10-20 меньше).
Я считаю, нативные потоки вполне жизнеспособны для большинства приложений.
𝙽𝚒𝚌𝚔
(команда выше означает "контекст 1мб переключать для 10, 20 и т.д. одновременных процессов, запускать 10 раз (-N 10) и усреднять результат")
𝙽𝚒𝚌𝚔
переключение в токио выглядит почти бесплатным, я не спорю.
Alexander
Aleksey
Alexander
А за счет чего так получается?
А разве оно будет бесплатным (точнее быстрым) если внутри будет что-то работающее? А работающая нитка всё равно за это же время переключится возможно.
Aleksey
Alexander
Я тоже, просто интересно.
𝙽𝚒𝚌𝚔
нужна хорошая методика оценки издержек разных частей в приложениях основанных на event loop, epoll и вот этом всём. Нужно почитать на эту тему статей, в-общем...
Alexander
Получается выбор : 1) переключаемся всегда за 140, или 2) переключаемся от нуля до бесконечности. => Если надо что-то сделать в нитке больше 140мкрс, то смысла в асинке получится нет. (Кроме памяти)
𝙽𝚒𝚌𝚔
> 1) переключаемся всегда за 140
да, если памяти достаточно.
Berkus
Berkus
𝙽𝚒𝚌𝚔
> флашить кэши, таблицы страниц
это и в асинке присутствует.
Alexander
> писать веб-сервер прямо в контексте ядра
Так microkernel же, MirageOS на Ocaml и что там на Rust? Rumpkernel там и всякое такое...
Berkus
Alexander
Как это - противоположно?
Berkus
Как это - противоположно?
все сервисы - изолированные процессы, а коммуникации только через IPC; переключения контекстов процессора там на порядок больше чем в монолитном ядре
Alexander
Berkus
> писать веб-сервер прямо в контексте ядра
Так microkernel же, MirageOS на Ocaml и что там на Rust? Rumpkernel там и всякое такое...
Berkus
Berkus
rumpkernel это вообще другое, там фича в эмуляции а не в скорости
Alexander
Но в L4 микроядрах переключение контекста если не на порядок, то в разы быстрее, чем в Linux/Windows.
Berkus
Berkus
user -> ipc -> security server -> ipc -> fs server -> ips -> pagecache server -> ipc -> ...
Alexander
Berkus
Berkus
показать тебе вскрытие микроядерной оси на одной игровой консоли switch?
Berkus
вполне себе штука из прода
Alexander
Но с тем, что unikernel как раз реализует переключение потоков и весь сервер прямо в ядре никто не спорит, так? 😊
Berkus
Berkus
чтобы не совсем офтоп )
Berkus
микроядреность там так себе, но я конечно spoiled by L4
Alexander
Про то и речь, что некоторые (многие?) успешный продакшен и на так себе технологиях строят. Я бы не стал на них ориентироваться.
Vladimir
А стек он разве не в виртуальной памяти живёт?
Berkus
Berkus
хотя где там нынче стек я хз
𝙽𝚒𝚌𝚔
И спустя 10 лет что изменилось? Я вижу появляющиеся процы с 100500 ядрами, а ты?
Berkus
Vladimir
Aleksey
А где начало батлла nio vs async vs others? Я пока попкорн искал, нить потерял, а тема интересная.
Vladimir
Тут
Vladimir
https://thetechsolo.wordpress.com/2016/08/28/scaling-to-thousands-of-threads/
Блокирующий IO быстрее NIO примерно на 25%, а с NPTL вы можете иметь сотни тысяч потоков.
Berkus
Berkus