[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: filling up, flushing and inserting again sometimes fails
- To: openldap-technical@openldap.org
- Subject: Re: filling up, flushing and inserting again sometimes fails
- From: Dominik Taborsky <dominik.taborsky@nic.cz>
- Date: Fri, 29 May 2015 10:27:06 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=simple/simple; d=nic.cz; s=default; t=1432888039; bh=7r8qckbBd3C4l3OIb8z+ehTo+7KdUoVmnuuBg7jSA8o=; h=Message-ID:Date:From:MIME-Version:To:Subject:References: In-Reply-To:Content-Type:Content-Transfer-Encoding; b=GWJmJzzHsUJocOh5ttYbZD1AX1h7QYlLD54Fd6GlUeNSzPu1TLDKgPnRwNPfeIcHx X6fsBbDAtrO1c6l72YbeWUYi6azHHhKK5grvTuJITZ0dG0ml/ESN1w3tdO+bxdf0Kr kV6HNOKlvD6HQnwY0MDUajFKfcfjw1WCYZvri33g=
- In-reply-to: <555F37A7.3000905@nic.cz>
- References: <555F37A7.3000905@nic.cz>
- User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0
On 05/22/2015 04:05 PM, Dominik Taborsky wrote:
> Hello,
>
> I'm playing around with LMDB and I'd like to know more about how it
> deletes items and reclaims space. I've been having some problems with
> this lately.
>
> For simplicity I'm testing smaller 20MiB DBs with data values of
> sizes from 40B to 4000B. The test checks all kinds of stuff, but
> mainly tries to do a few fillups and flushes in short sequence. The
> first cycle slowly increases the size of the data until the DB is
> full, then it flushes. Then 10 cycles of fillup-flush of static-sized
> data follow. For flushing I've been doing both mdb_drop and removing
> batches of stored data. I've tried batches of sizes between 2 and 100
> items. The results differ very much, depending on all these
> parameters: (only the 10 equal cycles counted):
I'd like to add that I tested this with LMDB 0.9.14 and git version from Tue 10 Feb 2015 (from AUR).
For the source code part, that's a bit harder - LMDB is wrapped in our library, which generalizes the API for transparent use with another backend. It also adds aforementioned fillup check and (optional) flushing-per-batches. But to at least outline the use:
size_t size = 300;
for (; ret == KNOT_EOK && key < 5000; ++key) {
data d;
random_data(&d, key, size);
size *= 1.5;
ret = db_store_data(db, &d);
data_clear(&d);
db_flush(db);
}
db_close(db);
int i, count;
size = 4000;
for (i = 0; i < 10; ++i) {
ret = KNOT_EOK;
count = 0;
for (; ret == KNOT_EOK && key < 5000; ++key) {
data_t d;
random_data(&d, key, size);
j = db_open(path, mapsize);
ret = db_store_data(db, &d);
if (ret == KNOT_EOK)
++count;
db_close(db);
data_clear(&d);
}
//test the insert
ok(count > 0, "db: pass #%d fillup run", i + 1);
db = db_open(path, mapsize);
db_flush(db);
db_close(db);
}
I've edited the code a bit to make it more readable (it's an excerpt from a unittest) and clear. The fillup protection code is here:
MDB_stat stat;
int ret = mdb_stat(txn->txn, env->dbi, &stat);
if (ret != MDB_SUCCESS) {
return lmdb_error_to_knot(ret);
}
MDB_envinfo envinfo;
ret = mdb_env_info(env->env, &envinfo);
if (ret != MDB_SUCCESS) {
return lmdb_error_to_knot(ret);
}
/* Guarantee there is enough space for erasing records from the DB. */
size_t used_pages = stat.ms_branch_pages + stat.ms_leaf_pages + stat.ms_overflow_pages;
size_t data_pages = val->len / stat.ms_psize;
size_t total_pages = envinfo.me_mapsize / stat.ms_psize;
if (used_pages + data_pages + CLEAR_PAGE_NO >= total_pages) {
return EBUSY;
}
Where CLEAR_PAGE_NO is currently defined to be 32.
If I could be of any further help to figure this out, let me know.
Thank you.
Best regards,
Dominik Taborsky