Хотелось построить сетевую подсистему, написанную на крестах, на такой идее: разные протоколы/модули обмениваются «цепочками буферов» (блохчейнами ога), в том числе и сетевая подсистема. Например, если кто-то хочет отправить по вебсокету 12 кб данных юзеру, то этот кто-то просит у центрального менеджера ресурсов 3 блока, наполняет их данными, чейнит их в одну цепь и кидает поинтер на первый блок в «сеть». Epoll-driven «сеть» отправит все данные (когда сможет) из этих блоков последовательно в сокет и отдаст «менеджеру ресурсов» блоки обратно по мере отправки. Блоки переюзываются всеми компонентами, потребляются по мере нужды, а новые коннекты не жрут память только по факту коннекта, тяжелее заддосить, всё красиво. Короче, общая идея в том, что есть некий slab-аллокатор блоков, владеющий ими и выдающий в аренду и блоки, протекая через все подсистемы и задерживаясь в сетевом модуле, если сразу запсать в сокет не удалось (больше чем TCP window или другой прикол), и в конце возвращаются в блокопрародитель обратно. Памяти при таком подходе в целом в любой момент сожрано меньше, чем если бы при наших 5к соединений каждый коннекшен бы держал собственный буфер на пару метров.
Одно но: если такая моя «сеть» решила вычитать из сокета мегабайт, то она сделает 1024/4 = 256 сисколлов read(), чтобы выжрать данные в цепь 4кб-блоков вместо одного сисколла, если бы у неё был буфер на 1 метр. На отправке те же приколы - рост числа сисколлов.
Да, есть оптимизации - можно юзать блоки разных размеров в разных местах, можно смотреть на Content-Length в случае протокола HTTP и готовиться к мегабайту оптимальнее заранее и т.п.
Но вот хотелось бы послушать разных историй про подобные «движки сети» где были похожие идеи и где авторы нашли оптимум.
Про recvmmsg/sendmmsg и io_uring в принципе в курсе.
UPDATE
«4 кб буферы» отошли в прошлое, текущее понимание затеи как «цепочка буферов разной фиксированной длины», например HTTP-ответ юзеру может быть цепочкой из буфера 4КБ (на хидеры) и за ним буфер в мегабайт под body.