Мы используем protobuf-net для сериализации и десериализации сообщений в приложении, общедоступный протокол которого основан на буферах протокола Google. Библиотека превосходна и покрывает все наши требования, кроме этого: нам нужно узнать длину сериализованного сообщения в байтах, прежде чем сообщение будет действительно сериализовано.
Вопрос уже задавался полтора года назад, и, по словам Марка, единственный способ сделать это - сериализовать его в MemoryStream и после этого прочитать свойство .Length
. В нашем случае это неприемлемо, потому что MemoryStream за кулисами выделяет байтовый буфер, и мы должны этого избежать.
Эта строка из того же ответа вселяет в нас надежду, что в конце концов это возможно:
Если вы проясните, каков вариант использования, я уверен, что мы сможем легко сделать его доступным (если это еще не было).
Вот наш пример использования. У нас есть сообщения размером от нескольких байтов до двух мегабайт. Приложение предварительно выделяет байтовые буферы, используемые для операций с сокетами и для сериализации / десериализации, и после завершения фазы прогрева дополнительные буферы не могут быть созданы (подсказка: avoding GC и фрагментация кучи). По сути, байтовые буферы объединены в пулы. Мы также хотим, насколько это возможно, избегать копирования байтов между буферами / потоками.
Мы придумали две возможные стратегии, и обе они требуют размера сообщения заранее:
Socket.Send
. Мы должны знать, когда следующее сообщение не может поместиться в буфер, и прекратить сериализацию. Без размера сообщения единственный способ добиться этого - дождаться возникновения исключения во время Serialize
. Socket.Send
. Чтобы извлечь из пула байтовый буфер подходящего размера, нам нужно знать, сколько байтов имеет сериализованное сообщение. Поскольку протокол уже определен (мы не можем это изменить) и требует, чтобы префикс длины сообщения был Varint32, мы не можем использовать метод SerializeWithLengthPrefix
.
Можно ли добавить в поток метод, оценивающий размер сообщения без сериализации? Если это что-то, что не вписывается в текущий набор функций и дорожную карту библиотеки, но выполнимо, мы заинтересованы в расширении библиотеки сами. Мы также ищем альтернативные подходы, если они есть.