diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-11-25 00:37:42 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-11-25 00:37:42 +0100 |
commit | e4a4d72fd206fc2d5c1095b39b2839e53cd114bb (patch) | |
tree | bf1edb0a483c12cda89973b3f073cd44b00286b4 /common/storage_lmdb.cpp | |
parent | 9ad96df6cd1526de32bff2b4f98491dd8318f760 (diff) | |
download | sink-e4a4d72fd206fc2d5c1095b39b2839e53cd114bb.tar.gz sink-e4a4d72fd206fc2d5c1095b39b2839e53cd114bb.zip |
Optimize findLast
This just gave a 700% boost to query performance from ~2k
to 14k reads per second...
Diffstat (limited to 'common/storage_lmdb.cpp')
-rw-r--r-- | common/storage_lmdb.cpp | 71 |
1 files changed, 59 insertions, 12 deletions
diff --git a/common/storage_lmdb.cpp b/common/storage_lmdb.cpp index 1516e69..a247e38 100644 --- a/common/storage_lmdb.cpp +++ b/common/storage_lmdb.cpp | |||
@@ -253,22 +253,69 @@ int Storage::NamedDatabase::scan(const QByteArray &k, | |||
253 | 253 | ||
254 | return numberOfRetrievedValues; | 254 | return numberOfRetrievedValues; |
255 | } | 255 | } |
256 | void Storage::NamedDatabase::findLatest(const QByteArray &uid, | 256 | |
257 | void Storage::NamedDatabase::findLatest(const QByteArray &k, | ||
257 | const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, | 258 | const std::function<void(const QByteArray &key, const QByteArray &value)> &resultHandler, |
258 | const std::function<void(const Storage::Error &error)> &errorHandler) const | 259 | const std::function<void(const Storage::Error &error)> &errorHandler) const |
259 | { | 260 | { |
260 | QByteArray latestKey; | 261 | if (!d || !d->transaction) { |
261 | scan(uid, [&](const QByteArray &key, const QByteArray &value) -> bool { | 262 | //Not an error. We rely on this to read nothing from non-existing databases. |
262 | latestKey = key; | 263 | return; |
263 | return true; | 264 | } |
264 | }, | ||
265 | errorHandler, true); | ||
266 | 265 | ||
267 | scan(latestKey, [=](const QByteArray &key, const QByteArray &value) -> bool { | 266 | int rc; |
268 | resultHandler(key, value); | 267 | MDB_val key; |
269 | return false; | 268 | MDB_val data; |
270 | }, | 269 | MDB_cursor *cursor; |
271 | errorHandler); | 270 | |
271 | key.mv_data = (void*)k.constData(); | ||
272 | key.mv_size = k.size(); | ||
273 | |||
274 | rc = mdb_cursor_open(d->transaction, d->dbi, &cursor); | ||
275 | if (rc) { | ||
276 | Error error(d->name.toLatin1(), getErrorCode(rc), QByteArray("Error during mdb_cursor open: ") + QByteArray(mdb_strerror(rc))); | ||
277 | errorHandler ? errorHandler(error) : d->defaultErrorHandler(error); | ||
278 | return; | ||
279 | } | ||
280 | |||
281 | MDB_cursor_op op = MDB_SET_RANGE; | ||
282 | if ((rc = mdb_cursor_get(cursor, &key, &data, op)) == 0) { | ||
283 | //The first lookup will find a key that is equal or greather than our key | ||
284 | if (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { | ||
285 | bool advanced = false; | ||
286 | while (QByteArray::fromRawData((char*)key.mv_data, key.mv_size).startsWith(k)) { | ||
287 | advanced = true; | ||
288 | MDB_cursor_op nextOp = MDB_NEXT; | ||
289 | rc = mdb_cursor_get(cursor, &key, &data, nextOp); | ||
290 | if (rc) { | ||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | if (advanced) { | ||
295 | MDB_cursor_op prefOp = MDB_PREV; | ||
296 | //We read past the end above, just take the last value | ||
297 | if (rc == MDB_NOTFOUND) { | ||
298 | prefOp = MDB_LAST; | ||
299 | } | ||
300 | rc = mdb_cursor_get(cursor, &key, &data, prefOp); | ||
301 | resultHandler(QByteArray::fromRawData((char*)key.mv_data, key.mv_size), QByteArray::fromRawData((char*)data.mv_data, data.mv_size)); | ||
302 | } | ||
303 | } | ||
304 | } | ||
305 | |||
306 | //We never find the last value | ||
307 | if (rc == MDB_NOTFOUND) { | ||
308 | rc = 0; | ||
309 | } | ||
310 | |||
311 | mdb_cursor_close(cursor); | ||
312 | |||
313 | if (rc) { | ||
314 | Error error(d->name.toLatin1(), getErrorCode(rc), QByteArray("Key: ") + k + " : " + QByteArray(mdb_strerror(rc))); | ||
315 | errorHandler ? errorHandler(error) : d->defaultErrorHandler(error); | ||
316 | } | ||
317 | |||
318 | return; | ||
272 | } | 319 | } |
273 | 320 | ||
274 | 321 | ||