Closed
Description
Given the following example:
NAPI_METHOD(db_get_many) {
NAPI_ARGV(2);
Database* database;
NAPI_STATUS_THROWS(napi_get_value_external(env, argv[0], reinterpret_cast<void**>(&database)));
// TODO (fix): Ensure lifetime of buffer?
std::vector<rocksdb::Slice> keys;
{
uint32_t length;
NAPI_STATUS_THROWS(napi_get_array_length(env, argv[1], &length));
keys.reserve(length);
for (uint32_t n = 0; n < length; n++) {
napi_value element;
char* buf;
size_t length;
NAPI_STATUS_THROWS(napi_get_element(env, argv[1], n, &element));
NAPI_STATUS_THROWS(napi_get_buffer_info(env, element, reinterpret_cast<void**>(&buf), &length));
keys.emplace_back(rocksdb::Slice{buf, length});
}
}
rocksdb::ColumnFamilyHandle* column = database->db->DefaultColumnFamily();
rocksdb::ReadOptions readOptions;;
const auto size = keys.size();
std::vector<rocksdb::Status> statuses;
std::vector<rocksdb::PinnableSlice> values;
statuses.resize(size);
values.resize(size);
database->db->MultiGet(readOptions, column, size, keys.data(), values.data(), statuses.data());
for (size_t idx = 0; idx < size; idx++) {
if (statuses[idx].IsNotFound()) {
values[idx] = rocksdb::PinnableSlice(nullptr);
} else {
ROCKS_STATUS_THROWS_NAPI(statuses[idx]);
}
}
napi_value ret;
NAPI_STATUS_THROWS(napi_create_array_with_length(env, values.size(), &ret));
for (size_t idx = 0; idx < values.size(); idx++) {
napi_value element;
if (values[idx].GetSelf()) {
auto ptr = new rocksdb::PinnableSlice(std::move(values[idx]));
NAPI_STATUS_THROWS(napi_create_external_buffer(env, ptr->size(), const_cast<char*>(ptr->data()), Finalize<rocksdb::PinnableSlice>, ptr, &element));
} else {
NAPI_STATUS_THROWS(napi_get_undefined(env, &element));
}
NAPI_STATUS_THROWS(napi_set_element(env, ret, static_cast<uint32_t>(idx), element));
}
return ret;
}
more than 50% of the time is spent with napi_create_external_buffer
which I would assume should be a rather fast operation...
Metadata
Metadata
Assignees
Type
Projects
Status
Done