2012-01-16 15 views
5

Tôi có một ứng dụng C# mà cần phải deserialize hàng ngàn tin nhắn protobuf mỗi giây. Vì lợi ích của việc tránh các bộ sưu tập rác không cần thiết, tôi tự hỏi nếu có một cách để sử dụng bộ nhớ được cấp phát trước để mỗi hoạt động deserialization sẽ không cần phải cấp phát bộ nhớ mới.Sử dụng protobuf-net, có thể deserialize một tin nhắn mà không cần phân bổ bộ nhớ?

Những gì tôi hình dung là tôi sẽ phân bổ một nhóm các đối tượng tin nhắn trước khi thực thi, và sau đó hướng dẫn mã protobuf sử dụng thông báo tiếp theo từ hồ bơi này cho mỗi lần deserialization.

Chức năng này có tồn tại hay có cách nào khác để tối ưu hóa việc sử dụng bộ nhớ trong trường hợp này?

Cảm ơn!

+2

Bạn đã xác định rằng đây thực tế là vấn đề? Bạn có gặp phải tình huống này khi ứng dụng của bạn đang chạy thấp trên bộ nhớ hoặc đang chạy chậm do bộ sưu tập rác không? – BFree

+0

Không, nhưng đó là vùng duy nhất của mã trong thành phần tần số cao này hiện đang được yêu cầu cấp phát bộ nhớ, do đó, có vẻ đáng giá để tôi khám phá khả năng loại bỏ nó, đặc biệt nếu có cách tiếp cận đơn giản. – newdayrising

+0

Phân bổ và thu gom rác của các đối tượng ngắn ngủi cực kỳ nhanh.Bạn có lẽ không nên lo lắng về điều này trừ khi bạn thực sự hồ sơ mã của bạn và tìm hiểu đây là nút cổ chai. – svick

Trả lời

10

Có, có! Bên trong, nó đã sử dụng một nhóm vi sinh để tránh phân bổ quá nhiều vùng đệm làm việc, nhưng nếu bạn đang đặt đủ các đối tượng mà GC là một vấn đề, bạn có thể sử dụng lược đồ phân bổ của riêng mình và tạo một nhà máy đối tượng tùy chỉnh; này không thể được xác định trên thuộc tính hiện nay, nhưng có thể được áp dụng thông qua các loại mô hình:

RuntimeTypeModel.Default.Add(typeof (Foo), true).SetFactory(factory); 

nơi factory là một trong hai:

  • các tên của một phương pháp static trên Foo (tức là "CreateFoo") trả về một số Foo
  • MethodInfo của bất kỳ phương thức static nào (không cần được trên Foo) mà trả về một Foo

trong cả hai trường hợp, phương pháp có thể sử dụng chữ ký giống như callbacks - vì vậy nó có thể được parameterless, hoặc có thể chấp nhận thông tin ngữ cảnh. Ví dụ:

public static Foo CreateFoo() { 
    return GetFromYourOwnMicroPool(); 
} 

Lưu ý rằng trong việc sử dụng này, đó là mong rằng nhà máy sẽ thiết lập lại các đối tượng đến một nhà nước vani; protobuf-net sẽ không cố gắng làm điều này. Cũng lưu ý rằng hiện tại protobuf-net không cho thấy nó là một nhóm vi sinh như một thành phần có thể sử dụng lại được, nhưng bạn có thể tái sử dụng nguồn một cách dễ dàng.

Chức năng này đã được cụ thể thêm để hỗ trợ người dùng với thông lượng rất cao, những người muốn loại bỏ ngay cả những chi phí chung GC nhỏ nhất (dựa trên rất nhiều phép đo ... họ đã gửi cho tôi đồ thị xinh đẹp và tất cả mọi thứ; p)

Ngoài : ngoại trừ đối tượng gốc, protobuf-net hỗ trợ struct giá trị không có quyền chọn; vì vậy nếu bạn có mô hình đối tượng phức tạp/lồng nhau, một tùy chọn khác trong trường hợp cực đoan là xem struct s.

+0

Bạn có thể làm rõ cách sử dụng cấu trúc không? Chúng ta có thể làm điều đó khi tạo ra từ một tập tin proto? Điều gì về tuyên bố này trên github readme? 'Mã giả định rằng các loại sẽ có thể thay đổi xung quanh các thành viên được bầu. Theo đó, các cấu trúc tùy chỉnh không được hỗ trợ, vì chúng không thay đổi.' – Aranda

+0

@Aranda nhận xét đó có thể được hỗ trợ trước cho các cấu trúc. Công cụ tạo ra chỉ phát ra các lớp vào lúc này, nhưng các cấu trúc sẽ hoạt động tốt. –

+0

Cảm ơn Marc. Tôi đã làm cho nó hoạt động bằng cách chỉnh sửa thủ công các lớp được tạo thành các cấu trúc (cho các kiểu không phải root), nhưng không thể loại bỏ tất cả các phân bổ vì cách tiếp cận nhà máy và cách tiếp cận hợp nhất dường như không loại bỏ việc phân bổ các kiểu gốc. Chúng tôi đang thử chuyển sang Flatbuffers ngay bây giờ. – Aranda

Các vấn đề liên quan