Допустим у нас есть stream socket (например
boost::asio::ip::tcp::socket) с асинхронными операциями чтения/записи, а-ля async_read/async_write.
По этому потоку нужно гонять туда-сюда древовидные структуры, то есть обыкновенная сериализация.
Эти структуры не trivially copyable (как минимум потому, что содержат массивы переменной длины) — следовательно zero-copy никак не получится.
Простейшим вариантом для сериализации/десериализации является работа через промежуточный буфер в который помещаются сырые байты всей структуры целиком (в поток записывается размер всей структуры, поэтому при чтении можно аллоцировать буфер подходящего размера).
Но смотрю я на этот вариант и мне грустно от того, что происходит перерасход памяти
Эти структуры могут занимать от пары кибибайт до нескольких мебибайт, а соединений — десятки тысяч.
Возможно несколько уменьшить масштаб проблемы распилив крупные корневые структуры на несколько маленьких.
Более экономичным был бы вариант с использованием небольшого буфера фиксированного размера, например 32KiB — и соответственно поэтапная сериализация. То есть прочитали один chunk и сразу его десериализовали (и vice versa для сериализации).
Также это избавило бы от необходимости искать место для буфера переменного размера.
Варианты которые позволили бы использовать фиксированный буфер:
Отдельный поток для сериализации. Это, естественно, совсем не интересно.
Stackful Coroutines — на мой взгляд самый лучший вариант. Да и к тому же они есть не просто в Boost, а даже прям в
Boost.Asio.
Описание схемы сериализации в специальном формате, например через expression templates (а-ля Boost.Proto), через гетерогенные последовательности (а-ля Boost.Fusion, тем более сейчас через него всё и сериализуется), либо через препроцессор (BOOST_PP_SEQ или X-Macro) — и последующий распил считывания кусочков данных на continuations.
Внешняя генерация необходимого кода из схемы — а-ля Apache Thrift или Protocol Buffers (кстати, а может там уже есть асинхронная сериализация?).
Собственно у меня два вопроса:
1. Какие есть ещё альтернативы? Возможно есть какие-то стандартные/распространённые решения?
2. Встречалась ли вам такая задача? В каком контексте? И как она была решена?
Спасибо.