verement / lmdb-simple

Simple Haskell API for LMDB
https://hackage.haskell.org/package/lmdb-simple
BSD 3-Clause "New" or "Revised" License
12 stars 11 forks source link

Add openEnvironmentWithFlags #2

Open mihaigiurgeanu opened 6 years ago

mihaigiurgeanu commented 6 years ago

Add a new function, openEnvironmentWithFlags, to pass various flags when opening an environment. Useful if you want to use things like MDB_NOSYNC optimization.

verement commented 6 years ago

Thanks for this proposal.

There are several reasons I hesitate to merge this as-is. In general, I think it works against the theme of keeping things simple; I would prefer not to directly expose any of the lower-level API. But there are also hidden traps: some flag combinations can be dangerous or lead to unexpected consequences. For example:

I think I would prefer to provide a safer API for any of the flags that may actually be useful. For example, the MDB_NOMETASYNC and MDB_NOSYNC flags can be changed after the environment is opened, but to be most useful a function to call mdb_env_sync (and/or mdb_env_sync_flush) should also be provided.

Can you tell me which flags in particular you think are useful to modulate?

mihaigiurgeanu commented 6 years ago

Well, I really needed to use the MDB_NOSYNC flag for performance reasons, so I made this quick hack. For me it is not important if the database would become invalid in the case of a system crush, because the database can be restored, but it is important to have high speed for database writes. It is also a feature I am using in a prototype, maybe it will not be used in the production version, but for this prototype it is crucial for me to get the performance given by the MDB_NOSYNC flag.

The idea is that, in the rare occasions when you need one of these flags, if this library does not allow you to use them you would have the option to use the lower level api. But you would miss all the nice things in this library.

Would you consider making this function part of a module named with unsafe, like Database.LMDB.Simple.Unsafe? Or to include the unsafe word in the function name, for example openEnvironmentUnsafe and to document it in a special Unsafe functions section? Or to have only the flags that make sense exposed?

verement commented 6 years ago

I’m thinking perhaps there could be an API like this:

delaySync     :: Environment ReadWrite → IO a → IO a
delayMetaSync :: Environment ReadWrite → IO a → IO a

These would each set the MDB_NOSYNC or MDB_NOMETASYNC flags, respectively, in the environment for the duration of the IO action, then call mdb_env_sync_flush before returning.

Do you think this is a good idea and would it satisfy your needs?