2009-09-30 31 views
7

Tôi muốn tìm ra cách tối ưu để lưu trữ một số loại dữ liệu chung không được bao gồm trong danh sách được bộ đệm giao thức hỗ trợ.Cách tốt nhất để sử dụng số thập phân và thời gian biểu với bộ đệm giao thức là gì?

  • datetime (giây chính xác)
  • datetime (mili giây chính xác)
  • thập phân với độ chính xác cố định
  • thập phân với độ chính xác biến
  • rất nhiều giá trị bool (nếu bạn có rất nhiều trong số họ có vẻ như bạn sẽ có chi phí 1-2 byte cho mỗi thẻ do các thẻ của chúng.

Ngoài ra, ý tưởng là lập bản đồ cho chúng rất dễ dàng để sửa lỗi Các kiểu dữ liệu C++/Python/Java.

Trả lời

3

Lý do thiết kế protobuf có nhiều khả năng duy trì hỗ trợ kiểu dữ liệu dưới dạng "gốc" nhất có thể, để dễ dàng áp dụng các ngôn ngữ mới trong tương lai. Tôi cho rằng họ có thể cung cấp các loại tin nhắn trong xây dựng, nhưng bạn vẽ đường ở đâu?

Giải pháp của tôi là tạo ra hai loại thông điệp:

DateTime 
TimeSpan 

này chỉ là vì tôi đến từ một nền C#, nơi những loại được coi là đương nhiên.

Nhìn lại, TimeSpanDateTime có thể đã quá mức cần thiết, nhưng đó là cách "rẻ" để tránh chuyển đổi từ h/m/s sang s và ngược lại; nói rằng, thật đơn giản khi chỉ cần triển khai chức năng tiện ích như:

int TimeUtility::ToSeconds(int h, int m, int s) 

Bklyn, chỉ ra rằng bộ nhớ heap được sử dụng cho thư lồng nhau; trong một số trường hợp, điều này rõ ràng là rất hợp lệ - chúng ta nên luôn biết cách sử dụng bộ nhớ. Nhưng, trong các trường hợp khác, điều này có thể ít quan tâm hơn, nơi mà chúng tôi lo lắng nhiều hơn về tính dễ triển khai (đây là triết lý Java/C# mà tôi cho là).

Ngoài ra còn có một bất lợi nhỏ khi sử dụng các loại không nội tại với protobuf TextFormat::Printer; bạn không thể chỉ định định dạng được hiển thị, vì vậy nó sẽ trông giống như sau:

my_datetime { 
    seconds: 10 
    minutes: 25 
    hours: 12 
} 

... quá dài đối với một số. Điều đó nói rằng, sẽ khó đọc hơn nếu nó được biểu diễn bằng giây.

Để kết luận, tôi muốn nói:

  • Nếu bạn đang lo lắng về bộ nhớ/phân tích hiệu quả, sử dụng giây/mili giây.
  • Tuy nhiên, nếu dễ thực hiện là mục tiêu, hãy sử dụng thư lồng nhau (DateTime, v.v.).
2

Xin lỗi, không phải là câu trả lời hoàn chỉnh, mà còn là "tôi cũng vậy".

Tôi nghĩ đây là một câu hỏi hay, tôi rất muốn có câu trả lời cho chính mình. Không có khả năng tự nhiên mô tả các kiểu cơ bản như datetimes và (đối với các ứng dụng tài chính) số thập phân cố định, hoặc ánh xạ chúng thành các kiểu được chỉ định theo ngôn ngữ hoặc do người dùng định nghĩa là một kẻ giết người thực sự đối với tôi. Nó ít nhiều ngăn cản tôi không thể sử dụng thư viện mà tôi nghĩ là tuyệt vời. Khai báo "DateTime" hoặc "FixedPoint" của riêng bạn trong ngữ pháp proto không thực sự là giải pháp, bởi vì bạn vẫn sẽ cần phải chuyển đổi biểu diễn của nền tảng của bạn thành/từ các đối tượng được tạo theo cách thủ công, dễ bị lỗi. Ngoài ra, các thư lồng nhau này được lưu trữ dưới dạng con trỏ tới các đối tượng được cấp phát đống trong C++, điều này cực kỳ không hiệu quả khi kiểu cơ bản về cơ bản chỉ là một số nguyên 64 bit.

Cụ thể, tôi muốn để có thể viết một cái gì đó như thế này trong file proto tôi:

message Something { 
    required fixed64 time = 1 [cpp_type="boost::posix_time::ptime"]; 
    required int64 price = 2 [cpp_type="fixed_point<int64_t, 4>"]; 
    ... 
}; 

Và tôi sẽ được yêu cầu cung cấp bất cứ keo là cần thiết để chuyển đổi các loại đến/từ fixed64 và int64 để tuần tự hóa sẽ hoạt động. Có lẽ thông qua một cái gì đó như adobe::promote?

3

Dưới đây là một số ý tưởng dựa trên kinh nghiệm của tôi với giao thức dây tương tự như Protocol Buffers.

datetime (giây chính xác)

datetime (mili giây chính xác)

Tôi nghĩ rằng câu trả lời cho hai sẽ là như nhau, bạn sẽ chỉ thường được giao dịch với một phạm vi nhỏ hơn số trong trường hợp độ chính xác giây.

Sử dụng sint64/sfixed64 để lưu trữ độ lệch theo giây/mili giây từ một số kỷ nguyên nổi tiếng như nửa đêm GMT 1/1/1970. Các đối tượng Date date này là internally represented in Java. Tôi chắc rằng có những tương tự trong Python và C++.

Nếu bạn cần thông tin múi giờ, hãy vượt qua ngày/giờ của bạn theo UTC và lập mô hình múi giờ thích hợp làm trường chuỗi riêng biệt. Đối với điều đó, bạn có thể sử dụng số nhận dạng từ Olson Zoneinfo database vì từ đó đã trở thành tiêu chuẩn.

Bằng cách này bạn có một đại diện kinh điển cho ngày/giờ, nhưng bạn cũng có thể bản địa hóa cho bất kỳ múi giờ nào là thích hợp.

thập phân với độ chính xác cố định

Suy nghĩ đầu tiên của tôi là sử dụng một chuỗi tương tự như cách người ta xây dựng đối tượng Decimal từ gói số thập phân của Python. Tôi cho rằng điều đó có thể không hiệu quả so với một số biểu diễn bằng số.

Có thể có các giải pháp tốt hơn tùy thuộc vào miền bạn đang làm việc. Ví dụ, nếu bạn đang lập mô hình một giá trị tiền tệ, có lẽ bạn có thể lấy đi bằng cách sử dụng một uint32/64 để truyền đạt giá trị bằng cent so với số tiền đô la phân đoạn.

Ngoài ra còn có một số đề xuất hữu ích trong this thread.

thập phân với độ chính xác biến

Không Nghị định thư Buffers đã hỗ trợ này với phao/loại vô hướng đôi? Có lẽ tôi đã hiểu lầm điểm đạn này.

Dù sao, nếu bạn có nhu cầu đi xung quanh các loại vô hướng, bạn có thể mã hóa bằng IEEE-754 thành uint32 hoặc uint64 (float vs double tương ứng). Ví dụ: Java allows you to extract the IEEE-754 representationvice versa từ các đối tượng Nổi/Đôi. Có các cơ chế tương tự trong C++/Python.

rất nhiều giá trị bool (nếu bạn có rất nhiều trong số họ có vẻ như bạn sẽ có 1-2 byte mào đầu cho mỗi người trong số họ do thẻ của họ.

Nếu bạn là lo ngại về byte bị lãng phí trên dây, bạn có thể sử dụng bit-masking techniques để nén nhiều boolean thành một uint32 hoặc uint64 đơn.

Vì không có hỗ trợ lớp đầu tiên trong Bộ đệm giao thức, tất cả các kỹ thuật này yêu cầu một chút của một người dịu dàng ' -hợp đồng giữa các đại lý . Có lẽ sử dụng quy ước đặt tên trên các trường của bạn như "_dttm" hoặc "_mask" sẽ giúp giao tiếp khi một trường nhất định có ngữ nghĩa mã hóa bổ sung ở trên và vượt ra ngoài hành vi mặc định của Bộ đệm giao thức.

1

Đối với ngày giờ có độ phân giải giây, tôi đã sử dụng int64 có ngày giờ là YYYYMMDDHHMMSSmmm. Điều này làm cho cả hai ngắn gọn và dễ đọc, và đáng ngạc nhiên, sẽ kéo dài một thời gian rất dài.

Đối với số thập phân, tôi đã sử dụng byte[], biết rằng không có đại diện tốt hơn sẽ không bị mất mát.

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