-
Notifications
You must be signed in to change notification settings - Fork 36
Description
leveldb-sharp currently copies the values returned from LevelDB using Marshal.PtrToStringAnsi() as the memory was allocated by LevelDB. The issue is that the CLR can not use memory owned / allocated by someone else it can't know when it needs to be released or if it was already released. The simple but not effective solution is to copy the memory to have it CLR owned. To make the situation even worse, the C binding of LevelDB also copies the values returned by LevelDB, see: http://codeofrob.com/entries/the-price-of-abstraction---using-leveldb-in-ravendb.html
After looking into this issue I came up these possible solutions how passing values can work:
- copy unmanaged memory and make the copy managed: Marshal.PtrToStringAnsi()
- Pros: safe, easy to implement, easy to use
- Cons: copy overhead
- return the pointer everywhere, as in IntPtr instead of a string or byte[] and let the user access that doing unsafe code blocks
- Pros: most efficient
- Cons: unsafe and ugly to use
- implement a Slice type that operates on IntPtr and do unsafe code access on it and release the memory when needed (GCed). This would be basically a safe proxy around the unsafe memory.
- Pros: safe, easy to use, most efficient
Quoting from Rob's blog:
MemoryStream stream = db.Get(string key)
"Where that stream reads from the start of an unmanaged array to the end of that unmanaged array and then disposes it."
This wouldn't work for us, as LevelDB reads the whole value into memory and returns that, instead of a stream...