Skip to content

Commit fbcdb7b

Browse files
committed
Create snapshot for get() synchronously
Has a tiny performance cost, which I negated by optimizing the passing of options from JS to C++. The end result is faster than before. However, I didn't check if it blocks the event loop for a significant amount of time. Benchmarking concurrent gets might answer that, later. Ref: Level/community#118 Category: fix
1 parent 7ca3de5 commit fbcdb7b

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

binding.cc

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,20 @@ static bool BooleanProperty (napi_env env, napi_value obj, const char* key,
189189
return DEFAULT;
190190
}
191191

192+
/**
193+
* Returns a boolean value.
194+
* Returns 'DEFAULT' if the JS value is undefined or otherwise not a boolean.
195+
*/
196+
static bool BooleanValue (napi_env env, napi_value value, bool DEFAULT) {
197+
bool result;
198+
199+
if (napi_get_value_bool(env, value, &result) == napi_ok) {
200+
return result;
201+
} else {
202+
return DEFAULT;
203+
}
204+
}
205+
192206
enum Encoding { buffer, utf8, view };
193207

194208
/**
@@ -211,6 +225,19 @@ static Encoding GetEncoding (napi_env env, napi_value options, const char* optio
211225
return Encoding::utf8;
212226
}
213227

228+
/**
229+
* Returns internal Encoding enum by its equivalent numeric value.
230+
*/
231+
static Encoding GetEncoding (napi_env env, napi_value value) {
232+
int32_t result;
233+
234+
if (napi_get_value_int32(env, value, &result) == napi_ok) {
235+
return static_cast<Encoding>(result);
236+
}
237+
238+
return Encoding::utf8;
239+
}
240+
214241
/**
215242
* Returns a uint32 property 'key' from 'obj'.
216243
* Returns 'DEFAULT' if the property doesn't exist.
@@ -1231,6 +1258,7 @@ struct GetWorker final : public PriorityWorker {
12311258
key_(key),
12321259
encoding_(encoding) {
12331260
options_.fill_cache = fillCache;
1261+
options_.snapshot = database->NewSnapshot();
12341262
}
12351263

12361264
~GetWorker () {
@@ -1239,6 +1267,7 @@ struct GetWorker final : public PriorityWorker {
12391267

12401268
void DoExecute () override {
12411269
SetStatus(database_->Get(options_, key_, value_));
1270+
database_->ReleaseSnapshot(options_.snapshot);
12421271
}
12431272

12441273
void HandleOKCallback (napi_env env, napi_deferred deferred) override {
@@ -1258,14 +1287,13 @@ struct GetWorker final : public PriorityWorker {
12581287
* Gets a value from a database.
12591288
*/
12601289
NAPI_METHOD(db_get) {
1261-
NAPI_ARGV(3);
1290+
NAPI_ARGV(4);
12621291
NAPI_DB_CONTEXT();
12631292
NAPI_PROMISE();
12641293

12651294
leveldb::Slice key = ToSlice(env, argv[1]);
1266-
napi_value options = argv[2];
1267-
const Encoding encoding = GetEncoding(env, options, "valueEncoding");
1268-
const bool fillCache = BooleanProperty(env, options, "fillCache", true);
1295+
const Encoding encoding = GetEncoding(env, argv[2]);
1296+
const bool fillCache = BooleanValue(env, argv[3], true);
12691297

12701298
GetWorker* worker = new GetWorker(
12711299
env, database, deferred, key, encoding, fillCache

index.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ class ClassicLevel extends AbstractLevel {
5656
}
5757

5858
async _get (key, options) {
59-
return binding.db_get(this[kContext], key, options)
59+
return binding.db_get(
60+
this[kContext],
61+
key,
62+
encodingEnum(options.valueEncoding),
63+
options.fillCache
64+
)
6065
}
6166

6267
async _getMany (keys, options) {
@@ -162,3 +167,12 @@ class ClassicLevel extends AbstractLevel {
162167
}
163168

164169
exports.ClassicLevel = ClassicLevel
170+
171+
// It's faster to read options in JS than to pass options objects to C++.
172+
const encodingEnum = function (encoding) {
173+
if (encoding === 'buffer') return 0
174+
if (encoding === 'utf8') return 1
175+
176+
/* istanbul ignore else: should not happen */
177+
if (encoding === 'view') return 2
178+
}

0 commit comments

Comments
 (0)