Chúng tôi đang sử dụng protobuf-net để tuần tự hóa và deserialization các thông điệp trong một ứng dụng có giao thức công khai dựa trên Bộ đệm giao thức của Google. Thư viện là tuyệt vời và bao gồm tất cả các yêu cầu của chúng tôi ngoại trừ một trong những yêu cầu này: chúng ta cần phải tìm ra chiều dài tin nhắn được tuần tự hóa theo byte trước khi thông điệp thực sự được tuần tự hóa.nội dung kích thước tin nhắn theo thứ tự protobuf-net
The question đã được hỏi một năm rưỡi trước và theo Marc, cách duy nhất để thực hiện việc này là để tuần tự hóa thành MemoryStream và đọc thuộc tính .Length
sau đó. Điều này là không thể chấp nhận được trong trường hợp của chúng ta, bởi vì MemoryStream phân bổ một bộ đệm byte đằng sau hậu trường và chúng ta phải tránh điều này.
Dòng này từ cùng một phản ứng cho chúng ta hy vọng rằng nó có thể là tốt sau khi tất cả:
Nếu bạn làm rõ những gì các use-case là, tôi chắc chắn rằng chúng ta có thể làm cho nó dễ dàng có sẵn (nếu nó chưa được).
Đây là trường hợp sử dụng của chúng tôi. Chúng tôi có các thông báo có kích thước khác nhau giữa nhiều byte và hai megabyte. Ứng dụng phân bổ trước các bộ đệm byte được sử dụng cho các hoạt động ổ cắm và tuần tự hóa/deserializing và khi giai đoạn khởi động kết thúc, không có bộ đệm bổ sung nào có thể được tạo (gợi ý: phân tích GC và phân mảnh đống). Bộ đệm byte cơ bản được gộp chung. Chúng tôi cũng muốn tránh sao chép byte giữa bộ đệm/luồng càng nhiều càng tốt.
Chúng tôi đã đưa ra hai chiến lược tốt và cả hai yêu cầu kích thước tin nhắn trả trước:
- Sử dụng (lớn) kích thước cố định byte bộ đệm và serialize tất cả các thư mà có thể phù hợp với một bộ đệm; gửi nội dung của bộ đệm bằng cách sử dụng
Socket.Send
. Chúng ta phải biết khi nào thông điệp tiếp theo không thể phù hợp với bộ đệm và dừng tuần tự hóa. Nếu không có kích thước tin nhắn, cách duy nhất để đạt được điều này là chờ một ngoại lệ xảy ra trong thời gianSerialize
. - Sử dụng bộ đệm byte có kích thước biến nhỏ (nhỏ) và tuần tự hóa từng thông điệp thành một bộ đệm; gửi nội dung của bộ đệm bằng cách sử dụng
Socket.Send
. Để kiểm tra bộ đệm byte với kích thước thích hợp từ hồ bơi, chúng ta cần phải biết bao nhiêu byte có một thông điệp tuần tự có.
Do giao thức đã được xác định (chúng tôi không thể thay đổi điều này) và yêu cầu tiền tố chiều dài tin nhắn là Varint32, chúng tôi không thể sử dụng phương pháp SerializeWithLengthPrefix
.
Vì vậy, có thể thêm phương pháp ước tính kích thước thư mà không cần tuần tự hóa vào luồng? Nếu nó là một cái gì đó mà không phù hợp với các tính năng hiện tại và lộ trình của thư viện, nhưng là doable, chúng tôi đang quan tâm đến việc mở rộng các thư viện chính mình. Chúng tôi cũng đang tìm cách tiếp cận thay thế, nếu có.
Về tiền tố độ dài và SerializeWithLengthPrefix: phương pháp có thể viết tiền tố được mã hóa dưới dạng Base128, Fixed32 và Fixed32BigEndian, nhưng nó không hỗ trợ loại Varint32. Giao thức của chúng tôi xác định cấu trúc thông báo sau: [type: varint32] [length: varint32] [message protobuf thực]. –
@Boris chính xác là những gì base-128 có số trường ** là **. Trường số sẽ là === loại (có thể với một sự thay đổi >> 3). Tôi cần xem * byte chính xác *, nhưng điều đó có thể sử dụng được. Nếu không, chỉ cần thêm kiểu thủ công và mã hóa bằng base-128 và trường 0 (sẽ bỏ qua số trường) –
Cảm ơn bạn đã làm rõ, tôi đoán tôi đã bỏ lỡ điều đó. Và cảm ơn bạn đã phản hồi chi tiết. Chúng tôi vẫn đang đánh giá các phương pháp tiếp cận có thể và cố gắng tìm ra cách tối ưu với việc phân phối dữ liệu và phân bổ bộ đệm ít nhất có thể. –