哪个KiokuDB后端适合我的序列化需求?

时间:2010-10-26 14:09:04

标签: perl serialization moose kiokudb

我使用KiokuDB来存储一些Moose对象和几个简单的数组结构(哈希和数组)。

我不需要任何花哨的搜索,交易等,简单的获取(lookup)对象的能力。此外,只要我完成创建数据库,就可以将其设置为只读。不会对其进行任何更改。

我使用KiokuDB的主要(唯一?)原因是保留对象图。

最大的对象,它占据了DB的总大小,是一个Moose对象,其中有一个相对较大的数组(让我们称这个对象为large_obj)。以前,我使用Storable + PerlIO::gzip甚至JSON + large_obj存储PerlIO::gzip(单独)。它运行良好,我对结果非常满意(使用gzip将商店文件压缩到原始大小的5%左右)。

还有另一个较小的Moose物体,它基本上是一个大约20-30k小Moose物体的阵列。

现在,在迁移到KiokuDB之后,我首先使用简单的Hash后端,然后再次将其转储到文件(使用Cmd)和PerlIO::gzip。这在large_obj相对较小的情况下非常有效,但是一旦它变大,我就会出现内存错误。我想支持的哈希不适合大对象。

然后我尝试了推荐的Berkeley后端,虽然它看起来像是一种矫枉过正(如上所述,我并不需要所有奇特的数据库功能)。它的工作速度比原始的Storable + PerlIO::gzip解决方案要慢得多,它占用的空间要大得多,并且对于较大的对象,它的内存也会耗尽! (我使用3GB RAM ubuntu)。

我也尝试了Files backend,但它失败了:

Too many open files at /usr/local/perls/perl-5.12.2/lib/site_perl/5.12.2/Directory/Transactional.pm line 130.
    (in cleanup) Too many open files at /usr/local/perls/perl-5.12.2/lib/site_perl/5.12.2/Directory/Transactional.pm line 130.

对于如何以节省空间的方式存储对象并维护对象图,您有什么建议吗?

1 个答案:

答案 0 :(得分:3)

使用Data::Serializer实现您自己的后端:

package KiokuDB::Backend::Serialize::Data::Serializer;
use Moose;
use Moose::Role;

use Data::Serializer;

use namespace::clean -except => 'meta';

with qw(
    KiokuDB::Backend::Serialize
    KiokuDB::Backend::Role::UnicodeSafe
    KiokuDB::Backend::Role::BinarySafe
);

has '_serializer' => (
    is       => 'ro',
    isa      => 'Data::Serializer',
    required => 1,
    lazy     => 1,
    default  => sub {
        Data::Serializer->new(
            serializer => 'FreezeThaw', # Storable, FreezeThaw, Data::Denter, Config::General, YAML, PHP::Serialization, XML::Dumper, and Data::Dumper
            digester   => 'MD5', # See http://search.cpan.org/~gaas/Digest-1.16/Digest.pm#Digest_speed
            compress   => 1,
            compressor => 'Compress::Zlib', # Compress::Zlib or Compress::PPMd
        );
    },
);

sub serialize {
    my ( $self, $entry ) = @_;

    return $self->_serializer->serialize($entry);
}

sub deserialize {
    my ( $self, $blob ) = @_;

    return $self->_serializer->deserialize($blob);
}

sub serialize_to_stream {
    my ( $self, $fh, $entry ) = @_;

    $self->_serializer->store( $entry, $fh );
}

sub deserialize_from_stream {
    my ( $self, $fh ) = @_;

    $self->_serializer->retrieve($fh);
}

__PACKAGE__