I'm currently using rocksdb 7.3.1 to test MultiGet API.
When I use db_bench, MultiGet(-multiread_batched=true) performs better than Get(-multiread_batched=false). Complete arguments are as follows.
./db_bench -use_existing_db=true --db=../../db_bench_test/mulitget_test -benchmarks="multireadrandom" -key_size=32 -value_size=512 -num=5000000 -batch_size=64 -multiread_batched=true -use_direct_reads=true -duration=60 -ops_between_duration_checks=1 -readonly=true -adaptive_readahead=true -threads=1 -cache_size=10485760000 -async_io=false -multiread_stride=40000
But when I write my own code to test MultiGet API, there is almost no difference in performance between MultiGet and Get. My simple test code is as follows.
#include <cassert>
#include <string>
#include <iostream>
#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"
#include "rocksdb/table.h"
using ROCKSDB_NAMESPACE::Status;
using rocksdb::Slice;
using rocksdb::PinnableSlice;
using ROCKSDB_NAMESPACE::Options;
using ROCKSDB_NAMESPACE::ReadOptions;
using ROCKSDB_NAMESPACE::WriteOptions;
int main() {
rocksdb::DB *db;
rocksdb::Options options;
options.create_if_missing = true;
options.create_missing_column_families = true;
rocksdb::BlockBasedTableOptions table_options;
table_options.no_block_cache = true;
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
rocksdb::Status status = rocksdb::DB::OpenForReadOnly(options, "DB", &db);
assert(status.ok());
Slice s[3] = {Slice("key1"), Slice("key2"), Slice("key3")};
PinnableSlice values[3];
Status stat[3];
auto opt = ReadOptions();
opt.adaptive_readahead = true;
db->MultiGet(opt, db->DefaultColumnFamily(), 3, s, values, stat);
for (int i = 0; i < 3; i++) {
assert(stat[i].ok());
}
for (int i = 0; i < 3; i++) {
std::cout << values[i].ToString() << std::endl;
}
delete db;
return 0;
}
It seems that db_bench can properly initialize io_uring while my code can't. Let's focus on the function PosixRandomAccessFile::MultiRead in env/io_posix.cc in rocksdb v7.3.1, and here is part of the code in this function.
620 #if defined(ROCKSDB_IOURING_PRESENT)
621 struct io_uring* iu = nullptr;
622 if (thread_local_io_urings_) {
623 iu = static_cast<struct io_uring*>(thread_local_io_urings_->Get());
624 if (iu == nullptr) {
625 iu = CreateIOUring();
626 if (iu != nullptr) {
627 thread_local_io_urings_->Reset(iu);
628 }
629 }
630 }
When db_bench reached line 622, thread_local_io_urings_ is not a nullptr. When my code reached the same line, thread_local_io_urings_ is a nullptr. So actually my code didn't use io_uring. How can I solve this problem?
Thanks a lot!