Как сделать ленивую десериализацию карты в Haskell

Аналогично этому вопросу @Gabriel Gonzalez: Как выполнить быструю десериализацию данных в Хаскель

У меня есть большая карта, полная целых чисел и текста, которую я сериализовал с помощью Cerial. Файл около 10M.

Каждый раз, когда я запускаю свою программу, я десериализую все это, чтобы иметь возможность искать несколько элементов. Десериализация занимает около 500 мс, что не имеет большого значения, но мне всегда нравится профилировать по пятницам.

Кажется расточительным всегда десериализовать от 100 тыс. до 1 млн элементов, когда мне нужны только некоторые из них.

Я попробовал decodeLazy, а также изменил карту на Data.Map.Lazy (не совсем понимая, как карта может быть ленивой, но ладно, она есть), и это не влияет на время, за исключением, может быть, немного медленнее.

Мне интересно, есть ли что-то, что может быть немного умнее, только загрузка и декодирование необходимого. Конечно, база данных, такая как sqlite, может быть очень большой, но она загружает только то, что нужно для выполнения запроса. Я хотел бы найти что-то подобное, но без создания схемы базы данных.

Обновлять

Знаете, что было бы здорово? Некоторый сплав Mongo с Sqlite. Например, у вас может быть база данных документов JSON с использованием хранилища плоских файлов ... и, конечно, кто-то сделал это https://github.com/hamiltop/MongoLiteDB ... в Ruby :(

Думал, что mmap может помочь. Попробовал библиотеку mmap и впервые за всю свою жизнь выдал ошибку GHCI. Не знаю, как можно даже сообщить об этой ошибке.

Пробовал библиотеку bytestring-mmap, работает, но без улучшения производительности. Просто замените это:

ser <- BL.readFile cacheFile

С этим:

ser <- unsafeMMapFile cacheFile

Обновление 2

keyvaluehash может быть просто билетом. Производительность кажется действительно хорошей. Но API странный, а документации нет, так что придется немного поэкспериментировать.

Обновление 3: я идиот

Ясно, что я хочу здесь не более ленивой десериализации карты. Мне нужна база данных типа «ключ-значение», и есть несколько доступных вариантов, таких как dvm, tokyo-cabinet и эта штука levelDB, которую я никогда раньше не видел.

Keyvaluehash выглядит как родная база данных ключей-значений Haskell, которая мне нравится, но я до сих пор не знаю о ее качестве. Например, вы не можете запросить у базы данных список всех ключей или всех значений (единственными реальными операциями являются readKey, writeKey и deleteKey), поэтому, если вам это нужно, вам придется хранить их где-то еще. Еще один недостаток заключается в том, что вы должны указать размер при создании базы данных. Я использовал размер 20M, так что у меня было бы много места, но фактическая база данных, которую он создал, занимает 266M. Не знаю, почему, поскольку нет строки документации.


person Michael Fox    schedule 25.10.2014    source источник
comment
Ваш вопрос отличается (и более интересен!), чем вопрос Габриэля. Ему нужна была скорость десериализации всего набора данных; вы хотите декодировать (и, возможно, читать) только то, что необходимо. Я не думаю, что вы найдете готовое решение; предполагая, что вы хотите искать элементы в своем Map, не придется ли вам десериализовать по крайней мере все ключи, при отсутствии особенно умной схемы десериализации с произвольным доступом?   -  person Christian Conkle    schedule 25.10.2014
comment
Я никогда не пробовал ничего подобного, но: используйте пользовательскую структуру сериализации, которая записывает ключи и их смещения в потоке. Затем десериализуйте ключи с помощью преобразователей в десериализаторы их значений. Если вы не хотите десериализовать все ключи, вы не можете использовать Data.Map, и поиск ключа будет больше связан с бинарным поиском в потоке или чем-то еще. Однако вы можете использовать (запоминаемую) функцию Key -> Value, если это все, что вам нужно.   -  person luqui    schedule 25.10.2014
comment
Вы можете использовать что-то вроде persistent, что хорошо поддерживается. Забудьте о keyvaluehash, если вы еще этого не сделали. Это была игрушка, а теперь мертвая игрушка.   -  person dfeuer    schedule 23.02.2016


Ответы (1)


Один из способов, которым я делал это в прошлом, — просто создать каталог, в котором каждому файлу присваивается серийный ключ. Можно использовать unsafeinterleaveIO для "преобразования" десериализованного содержимого каждого прочитанного файла, так что значения принудительно считываются только при чтении...

person sclv    schedule 22.02.2016