Я работаю над системой данных, в которой необходимо хранить большие объемы простых, расширяемых данных (наряду с некоторыми специальными индексами, которые мы разрабатываем самостоятельно, и это не является частью этого вопроса). Я ожидаю, что там будут храниться миллиарды записей, поэтому эффективная сериализация является ключевой частью системы. Сериализация должна быть быстрой, компактной и поддерживаться на нескольких платформах и языках (поскольку за упаковку и распаковку этих данных будет отвечать клиентский компонент, а не часть системы хранения).
Тип данных фактически является хэшем с необязательными парами ключ/значение. Ключи будут представлять собой небольшие целые числа (интерпретируемые на прикладном уровне). Значения могут быть различными простыми типами данных — String, Integer, Float.
В качестве технологии мы выбрали MessagePack, и я пишу код для выполнения сериализации данных с помощью msgpack-ruby.
Мне не нужна точность 64-битного числа с плавающей запятой Ruby. Ни одно из сохраняемых чисел не имеет значимой точности даже до 32-битных пределов. Поэтому я хочу использовать поддержку MessagePack для 32-битных значений с плавающей запятой. Это определенно существует. Однако поведение Ruby по умолчанию в любой 64-битной системе заключается в сериализации Float до 64 бит:
MessagePack.pack(10.3)
=> "\xCB@$\x99\x99\x99\x99\x99\x9A"
Глядя на код MessagePack, кажется, что есть метод MessagePack::Packer#write_float32
, и этот делает то, что я ожидаю:
MessagePack::DefaultFactory.packer.write_float32(10.3).to_s
=> "\xCAA$\xCC\xCD"
. . . но я не могу найти способ настроить упаковщик по умолчанию или создать новый, который будет использовать этот метод при сериализации более крупной структуры.
В качестве проверки моего понимания я попробовал это:
class Float
def to_msgpack_ext
packer.write_float32(self)
end
def self.from_msgpack_ext s
unpacker.read(s)
end
end
MessagePack::DefaultFactory.register_type(0, Float )
MessagePack.pack(10.3)
=> "\xCB@$\x99\x99\x99\x99\x99\x9A"
Никакой разницы. . . ясно, что я что-то упускаю или неправильно понимаю в объектной модели, используемой в MessagePack. Возможно ли то, что я хочу сделать, и что мне нужно сделать?