NAME
    CHI::Driver::LMDB - use OpenLDAPs LMDB Key-Value store as a cache
    backend.

VERSION
    version 0.002000

SYNOPSIS
      use CHI;

      my $cache = CHI->new(
        driver => 'LMDB',
        root_dir => 'some/path',
        namespace => "My::Project",
      );

    See "CHI" documentation for more details on usage.

ATTRIBUTES
  "dir_create_mode"
    What mode (if any) to use when creating "root_dir" if it does not exist.

      ->new(
        # Default is 775 = rwxr-xr-x
        dir_create_mode => oct 666,
      );

  "root_dir"
    The prefix directory the "LMDB" data store will be installed to.

      ->new(
        root_dir => 'some/path'
      )

    Default is:

      OSTEMPDIR/chi-driver-lmdb-$EUID

  "cache_size"
    The size in bytes for each database.

    This is a convenience wrapper for "mapsize" which supports suffixes:

      cache_size => 5  # 5 bytes
      cache_size => 5k # 5 Kilobytes
      cache_size => 5m # 5 Megabytes ( default )

    This is also designed for syntax compatibility with
    "CHI::Driver::FastMmap"

  "single_txn"
      single_txn => 1

    SPEED: For performance benefits, have a single transaction that lives
    from the creation of the CHI cache till its destruction.

    However, WARNING: this flag is currently a bit dodgy, and CHI caches
    being kept alive till global destruction WILL trigger a "SEGV", and
    potentially leave your cache broken.

    You can avoid this by manually destroying the cache with:

      undef $cache

    Prior to global destruction.

  "db_flags"
    Flags to pass to "OpenDB"/"LMDB_File->open".

    See "LMDB_File"'s constructor options for details.

      use LMDB_File qw( MDB_CREATE );

      db_flags => MDB_CREATE # default

  "tx_flags"
    Flags to pass to "LMDB::Env->new"

    See "LMDB::Env"'s constructor options for details.

    Default is 0

      tx_flags => 0 # no flags

  "put_flags"
    Flags to pass to "->put(k,v,WRITE_FLAGS)".

    See LMDB_File->put options for details.

  "mapsize"
    Passes through to "LMDB::Env->new( mapsize => ... )"

    Default value is taken from "cache_size" with some "m/k" math if its
    set.

  "maxreaders"
    Passes through to "LMDB::Env->new( maxreaders => ... )"

  "maxdbs"
    Passes through to "LMDB::Env->new( maxdbs => ... )"

    Defines how many CHI namespaces ( Databases ) a path can contain.

    Default is 1024.

  "mode"
    Passes through to "LMDB::Env->new( mode => ... )"

    Defines the permissions on created DB Objects.

    Defaults to "oct 600" == "-rw-------"

  "flags"
    Passes through to "LMDB::Env->new( flags => ... )"

PERFORMANCE
    If write performance is a little slow for you ( due to the defaults
    being a single transaction per SET/GET operation, and transactions being
    flushed to disk when written ), there are two ways you can make
    performance a little speedy.

  Single Transaction Mode.
    If you pass "single_txn => 1" the cache will be given a single
    transaction for the life of its existence. However, pay attention to the
    warnings about cleaning up properly in "single_txn".

    Also, this mode is less ideal if you want to have two processes sharing
    a cache, because the data won't be visible on the other one till it
    exits! ☺

  "NOSYNC" Mode.
    You can also tell LMDB NOT to call "sync" at the end of every
    transaction, and this will greatly improve write performance due to IO
    being greatly delayed.

    This greatly weakens the databases consistency, but that seems like a
    respectable compromise for a mere cache backend, where a missing record
    is a performance hit, not a loss of data.

      use LMDB_File qw( MDB_NOSYNC MDB_NOMETASYNC );
      ...
      my $cache = CHI->new(
        ...
        flags => MDB_NOSYNC | MDB_NOMETASYNC
      );

    This for me cuts down an operation that takes 30 seconds worth of writes
    down to 6 ☺.

Comparison vs FastMmap
    FastMmap is still faster for reads. Here is a simple comparison for runs
    of my "dep_changes.pl" utility which does a respectable amount of cache
    look-ups.

    Google Docs Image
    <https://docs.google.com/spreadsheets/d/13PVt7N9aBnbXpqgQPPTFFO2plaLEXfN
    iHGefyvc3gaI/pubchart?oid=25361389&format=interactive>

    For writes, whether or not FastMmap is faster depends on settings.

    *   "NOSYNC" + "single_txn = 1" tends to give faster performance than
        "FastMmap".

    *   "NOSYNC" + "single_txn = 0" gives comparable performance to
        "FastMmap"

    *   "SYNC" + "single_txn = 1" tends to give slightly worse performance
        than "FastMmap"

    Google Docs Image
    <https://docs.google.com/spreadsheets/d/13PVt7N9aBnbXpqgQPPTFFO2plaLEXfN
    iHGefyvc3gaI/pubchart?oid=390411539&format=interactive>

    However,

    *   "SYNC" + "single_txn = 0" gives much worse performance than all of
        the above.

    Google Docs Image
    <https://docs.google.com/spreadsheets/d/13PVt7N9aBnbXpqgQPPTFFO2plaLEXfN
    iHGefyvc3gaI/pubchart?oid=2027736788&format=interactive>

AUTHOR
    Kent Fredric <kentnl@cpan.org>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2014 by Kent Fredric
    <kentfredric@gmail.com>.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

