pmem / pmemkv

Key/Value Datastore for Persistent Memory
https://pmem.io
Other
399 stars 118 forks source link

Did I use 'Each' correctly? #123

Closed roblatham00 closed 6 years ago

roblatham00 commented 6 years ago

Wanted to get famliar with pmemkv api so wrote a writer and reader pair. The writer reads words out of a dictionary (like /usr/share/dict/words) and stores them in pmemkv. then the reader tries to read them back. Except my reader isn't reporting anything:

Writer:

#include <libpmemkv.h>

using namespace pmemkv;

#define MAX_WORD 256

int main(int argc, char **argv)
{
    FILE *dict;
    char buffer[MAX_WORD];
    int32_t buflen;

    KVEngine *kv = KVEngine::Open("kvtree2", argv[1], PMEMOBJ_MIN_POOL);

    dict = fopen(argv[2], "r");

    while (fgets(buffer, MAX_WORD, dict) != NULL) {
        buflen = strlen(buffer);
        kv->Put(buffer, "");
    }
    delete kv;

    return 0;
}

reader:


#include <iostream>
#include <libpmemkv.h>

using namespace pmemkv;

int main(int argc, char **argv)
{
    KVEngine  *kv = KVEngine::Open("kvtree2", argv[1], PMEMOBJ_MIN_POOL);

    auto cb = [](void * context, int32_t keybytes, int32_t valuebytes, const char *key, const char * value) {
        std::cout << "HI" << std::endl;
        std::cout<< key << " " << value << std::endl;
    };
    kv->Each(cb);
}
robfromboulder commented 6 years ago

Hi @roblatham00, please try the btree engine in place of kvtree2, and I bet this will work.

Please post back if you need any more help getting this running, happy to help!

Thanks, RobD

roblatham00 commented 6 years ago

Switched to btree but now I get a bad_allocation exception from make_persistent_atomic when storing the 64th word. I am only storing an empty string along with the keys so I don't think i'm hitting any 500 byte limit.

or did you mean btree only supports 500 bytes worth of anything?

robfromboulder commented 6 years ago

Hmm, please make sure you delete your persistent pool that's already around. I suspect this is due to opening the kvtree2 binary format using the btree engine, which is not something we actively prevent at this time.

With btree the values are limited to 500 bytes each, so you should be fine there.

roblatham00 commented 6 years ago

File is definitely zapped. I am faking this with a plain old file on a file system, so perhaps that is complicating things.

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
zsh: abort (core dumped)  ./writer kv.db words
robfromboulder commented 6 years ago

Oh duh, it's the pool filling up. Increase PMEMOBJ_MIN_POOL to a larger value. :smile:

roblatham00 commented 6 years ago

#define PMEMOBJ_MIN_POOL ((size_t)(1024 * 1024 * 8)) /* 8 MiB */

Just so I understand clearly: each key/value pair in pmemkv's btree engine consumes 128 KiB ?

roblatham00 commented 6 years ago

I doubled the pool size and put values in a loop until breaking out once std::bad_alloc is caught. Reader reads back 100 keys now.

thanks for the help.

robfromboulder commented 6 years ago

I don't think btree will be very space-efficient for this case, it's not variable-length so it's always going to write out a full entry even for an empty value. That said, I agree with you that space usage looks rather high here for the number of keys. I'm curious to dig into this a bit more and understand this better.

Anyway, great to hear that things are working, and thanks for trying out the API!

robfromboulder commented 6 years ago

Oh, I also wanted to mention -- using plain old files is totally ok for prototyping, but a few tips if you're going to do any benchmarking with larger pools:

Thanks!

robfromboulder commented 6 years ago

Hey @roblatham00, closing out this issue with a few follow-up notes: