Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251next_report_ += 100000;252fprintf(stderr, "... finished %d ops%30s\r", done_, "");253fflush(stderr);254}255}257void Stop(const Slice& name) {258double finish = Env::Default()->NowMicros() * 1e-6;260// Pretend at least one op was done in case we are running a benchmark261// that does not call FinishedSingleOp().262if (done_ < 1) done_ = 1;264if (bytes_ > 0) {265char rate[100];266snprintf(rate, sizeof(rate), "%6.1f MB/s",267(bytes_ / 1048576.0) / (finish - start_));268if (!message_.empty()) {269message_ = std::string(rate) + " " + message_;270} else {271message_ = rate;272}273}275fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),276(finish - start_) * 1e6 / done_, (message_.empty() ? "" : " "),277message_.c_str());278if (FLAGS_histogram) {279fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());280}281fflush(stdout);282}284public:285enum Order { SEQUENTIAL, RANDOM };286enum DBState { FRESH, EXISTING };288Benchmark()289: db_(nullptr),290num_(FLAGS_num),291reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),292bytes_(0),293rand_(301) {294std::vector<std::string> files;295std::string test_dir;296Env::Default()->GetTestDirectory(&test_dir);297Env::Default()->GetChildren(test_dir.c_str(), &files);298if (!FLAGS_use_existing_db) {299for (int i = 0; i < files.size(); i++) {300if (Slice(files[i]).starts_with("dbbench_polyDB")) {301std::string file_name(test_dir);302file_name += "/";303file_name += files[i];304Env::Default()->DeleteFile(file_name.c_str());305}306}307}308}310~Benchmark() {311if (!db_->close()) {312fprintf(stderr, "close error: %s\n", db_->error().name());313}314}316void Run() {317PrintHeader();318Open(false);320const char* benchmarks = FLAGS_benchmarks;321while (benchmarks != nullptr) {322const char* sep = strchr(benchmarks, ',');323Slice name;324if (sep == nullptr) {325name = benchmarks;326benchmarks = nullptr;327} else {328name = Slice(benchmarks, sep - benchmarks);329benchmarks = sep + 1;330}332Start();334bool known = true;335bool write_sync = false;336if (name == Slice("fillseq")) {337Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1);338DBSynchronize(db_);339} else if (name == Slice("fillrandom")) {340Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1);341DBSynchronize(db_);342} else if (name == Slice("overwrite")) {343Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1);344DBSynchronize(db_);345} else if (name == Slice("fillrandsync")) {346write_sync = true;347Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1);348DBSynchronize(db_);349} else if (name == Slice("fillseqsync")) {350write_sync = true;351Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1);352DBSynchronize(db_);353} else if (name == Slice("fillrand100K")) {354Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1);355DBSynchronize(db_);356} else if (name == Slice("fillseq100K")) {357Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1);358DBSynchronize(db_);359} else if (name == Slice("readseq")) {360ReadSequential();361} else if (name == Slice("readrandom")) {362ReadRandom();363} else if (name == Slice("readrand100K")) {364int n = reads_;365reads_ /= 1000;366ReadRandom();367reads_ = n;368} else if (name == Slice("readseq100K")) {369int n = reads_;370reads_ /= 1000;371ReadSequential();372reads_ = n;373} else {374known = false;375if (name != Slice()) { // No error message for empty name376fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());377}378}379if (known) {380Stop(name);381}382}383}385private:386void Open(bool sync) {387assert(db_ == nullptr);389// Initialize db_390db_ = new kyotocabinet::TreeDB();391char file_name[100];392db_num_++;393std::string test_dir;394Env::Default()->GetTestDirectory(&test_dir);395snprintf(file_name, sizeof(file_name), "%s/dbbench_polyDB-%d.kct",396test_dir.c_str(), db_num_);398// Create tuning options and open the database399int open_options =400kyotocabinet::PolyDB::OWRITER | kyotocabinet::PolyDB::OCREATE;401int tune_options =402kyotocabinet::TreeDB::TSMALL | kyotocabinet::TreeDB::TLINEAR;403if (FLAGS_compression) {404tune_options |= kyotocabinet::TreeDB::TCOMPRESS;405db_->tune_compressor(&comp_);406}407db_->tune_options(tune_options);408db_->tune_page_cache(FLAGS_cache_size);409db_->tune_page(FLAGS_page_size);410db_->tune_map(256LL << 20);411if (sync) {412open_options |= kyotocabinet::PolyDB::OAUTOSYNC;413}414if (!db_->open(file_name, open_options)) {415fprintf(stderr, "open error: %s\n", db_->error().name());416}417}419void Write(bool sync, Order order, DBState state, int num_entries,420int value_size, int entries_per_batch) {421// Create new database if state == FRESH422if (state == FRESH) {423if (FLAGS_use_existing_db) {424message_ = "skipping (--use_existing_db is true)";425return;426}427delete db_;428db_ = nullptr;429Open(sync);430Start(); // Do not count time taken to destroy/open431}433if (num_entries != num_) {434char msg[100];435snprintf(msg, sizeof(msg), "(%d ops)", num_entries);436message_ = msg;437}439// Write to database440for (int i = 0; i < num_entries; i++) {441const int k = (order == SEQUENTIAL) ? i : (rand_.Next() % num_entries);442char key[100];443snprintf(key, sizeof(key), "%016d", k);444bytes_ += value_size + strlen(key);445std::string cpp_key = key;446if (!db_->set(cpp_key, gen_.Generate(value_size).ToString())) {447fprintf(stderr, "set error: %s\n", db_->error().name());448}449FinishedSingleOp();450}451}453void ReadSequential() {454kyotocabinet::DB::Cursor* cur = db_->cursor();455cur->jump();456std::string ckey, cvalue;457while (cur->get(&ckey, &cvalue, true)) {458bytes_ += ckey.size() + cvalue.size();459FinishedSingleOp();460}461delete cur;462}464void ReadRandom() {465std::string value;466for (int i = 0; i < reads_; i++) {467char key[100];468const int k = rand_.Next() % reads_;469snprintf(key, sizeof(key), "%016d", k);470db_->get(key, &value);471FinishedSingleOp();472}473}474};476} // namespace leveldb478int main(int argc, char** argv) {479std::string default_db_path;480for (int i = 1; i < argc; i++) {481double d;482int n;483char junk;484if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) {485FLAGS_benchmarks = argv[i] + strlen("--benchmarks=");486} else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) {487FLAGS_compression_ratio = d;488} else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 &&489(n == 0 || n == 1)) {490FLAGS_histogram = n;491} else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) {492FLAGS_num = n;493} else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) {494FLAGS_reads = n;495} else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) {496FLAGS_value_size = n;497} else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) {498FLAGS_cache_size = n;499} else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) {500FLAGS_page_size = n;
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.