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.
251double micros = (now - last_op_finish_) * 1e6;252hist_.Add(micros);253if (micros > 20000) {254fprintf(stderr, "long op: %.1f micros%30s\r", micros, "");255fflush(stderr);256}257last_op_finish_ = now;258}260done_++;261if (done_ >= next_report_) {262if (next_report_ < 1000)263next_report_ += 100;264else if (next_report_ < 5000)265next_report_ += 500;266else if (next_report_ < 10000)267next_report_ += 1000;268else if (next_report_ < 50000)269next_report_ += 5000;270else if (next_report_ < 100000)271next_report_ += 10000;272else if (next_report_ < 500000)273next_report_ += 50000;274else275next_report_ += 100000;276fprintf(stderr, "... finished %d ops%30s\r", done_, "");277fflush(stderr);278}279}281void Stop(const Slice& name) {282double finish = Env::Default()->NowMicros() * 1e-6;284// Pretend at least one op was done in case we are running a benchmark285// that does not call FinishedSingleOp().286if (done_ < 1) done_ = 1;288if (bytes_ > 0) {289char rate[100];290snprintf(rate, sizeof(rate), "%6.1f MB/s",291(bytes_ / 1048576.0) / (finish - start_));292if (!message_.empty()) {293message_ = std::string(rate) + " " + message_;294} else {295message_ = rate;296}297}299fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),300(finish - start_) * 1e6 / done_, (message_.empty() ? "" : " "),301message_.c_str());302if (FLAGS_histogram) {303fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());304}305fflush(stdout);306}308public:309enum Order { SEQUENTIAL, RANDOM };310enum DBState { FRESH, EXISTING };312Benchmark()313: db_(nullptr),314db_num_(0),315num_(FLAGS_num),316reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),317bytes_(0),318rand_(301) {319std::vector<std::string> files;320std::string test_dir;321Env::Default()->GetTestDirectory(&test_dir);322Env::Default()->GetChildren(test_dir, &files);323if (!FLAGS_use_existing_db) {324for (int i = 0; i < files.size(); i++) {325if (Slice(files[i]).starts_with("dbbench_sqlite3")) {326std::string file_name(test_dir);327file_name += "/";328file_name += files[i];329Env::Default()->DeleteFile(file_name.c_str());330}331}332}333}335~Benchmark() {336int status = sqlite3_close(db_);337ErrorCheck(status);338}340void Run() {341PrintHeader();342Open();344const char* benchmarks = FLAGS_benchmarks;345while (benchmarks != nullptr) {346const char* sep = strchr(benchmarks, ',');347Slice name;348if (sep == nullptr) {349name = benchmarks;350benchmarks = nullptr;351} else {352name = Slice(benchmarks, sep - benchmarks);353benchmarks = sep + 1;354}356bytes_ = 0;357Start();359bool known = true;360bool write_sync = false;361if (name == Slice("fillseq")) {362Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1);363WalCheckpoint(db_);364} else if (name == Slice("fillseqbatch")) {365Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1000);366WalCheckpoint(db_);367} else if (name == Slice("fillrandom")) {368Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1);369WalCheckpoint(db_);370} else if (name == Slice("fillrandbatch")) {371Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1000);372WalCheckpoint(db_);373} else if (name == Slice("overwrite")) {374Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1);375WalCheckpoint(db_);376} else if (name == Slice("overwritebatch")) {377Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1000);378WalCheckpoint(db_);379} else if (name == Slice("fillrandsync")) {380write_sync = true;381Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1);382WalCheckpoint(db_);383} else if (name == Slice("fillseqsync")) {384write_sync = true;385Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1);386WalCheckpoint(db_);387} else if (name == Slice("fillrand100K")) {388Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1);389WalCheckpoint(db_);390} else if (name == Slice("fillseq100K")) {391Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1);392WalCheckpoint(db_);393} else if (name == Slice("readseq")) {394ReadSequential();395} else if (name == Slice("readrandom")) {396Read(RANDOM, 1);397} else if (name == Slice("readrand100K")) {398int n = reads_;399reads_ /= 1000;400Read(RANDOM, 1);401reads_ = n;402} else {403known = false;404if (name != Slice()) { // No error message for empty name405fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());406}407}408if (known) {409Stop(name);410}411}412}414void Open() {415assert(db_ == nullptr);417int status;418char file_name[100];419char* err_msg = nullptr;420db_num_++;422// Open database423std::string tmp_dir;424Env::Default()->GetTestDirectory(&tmp_dir);425snprintf(file_name, sizeof(file_name), "%s/dbbench_sqlite3-%d.db",426tmp_dir.c_str(), db_num_);427status = sqlite3_open(file_name, &db_);428if (status) {429fprintf(stderr, "open error: %s\n", sqlite3_errmsg(db_));430exit(1);431}433// Change SQLite cache size434char cache_size[100];435snprintf(cache_size, sizeof(cache_size), "PRAGMA cache_size = %d",436FLAGS_num_pages);437status = sqlite3_exec(db_, cache_size, nullptr, nullptr, &err_msg);438ExecErrorCheck(status, err_msg);440// FLAGS_page_size is defaulted to 1024441if (FLAGS_page_size != 1024) {442char page_size[100];443snprintf(page_size, sizeof(page_size), "PRAGMA page_size = %d",444FLAGS_page_size);445status = sqlite3_exec(db_, page_size, nullptr, nullptr, &err_msg);446ExecErrorCheck(status, err_msg);447}449// Change journal mode to WAL if WAL enabled flag is on450if (FLAGS_WAL_enabled) {451std::string WAL_stmt = "PRAGMA journal_mode = WAL";453// LevelDB's default cache size is a combined 4 MB454std::string WAL_checkpoint = "PRAGMA wal_autocheckpoint = 4096";455status = sqlite3_exec(db_, WAL_stmt.c_str(), nullptr, nullptr, &err_msg);456ExecErrorCheck(status, err_msg);457status =458sqlite3_exec(db_, WAL_checkpoint.c_str(), nullptr, nullptr, &err_msg);459ExecErrorCheck(status, err_msg);460}462// Change locking mode to exclusive and create tables/index for database463std::string locking_stmt = "PRAGMA locking_mode = EXCLUSIVE";464std::string create_stmt =465"CREATE TABLE test (key blob, value blob, PRIMARY KEY(key))";466std::string stmt_array[] = {locking_stmt, create_stmt};467int stmt_array_length = sizeof(stmt_array) / sizeof(std::string);468for (int i = 0; i < stmt_array_length; i++) {469status =470sqlite3_exec(db_, stmt_array[i].c_str(), nullptr, nullptr, &err_msg);471ExecErrorCheck(status, err_msg);472}473}475void Write(bool write_sync, Order order, DBState state, int num_entries,476int value_size, int entries_per_batch) {477// Create new database if state == FRESH478if (state == FRESH) {479if (FLAGS_use_existing_db) {480message_ = "skipping (--use_existing_db is true)";481return;482}483sqlite3_close(db_);484db_ = nullptr;485Open();486Start();487}489if (num_entries != num_) {490char msg[100];491snprintf(msg, sizeof(msg), "(%d ops)", num_entries);492message_ = msg;493}495char* err_msg = nullptr;496int status;498sqlite3_stmt *replace_stmt, *begin_trans_stmt, *end_trans_stmt;499std::string replace_str = "REPLACE INTO test (key, value) VALUES (?, ?)";500std::string begin_trans_str = "BEGIN TRANSACTION;";
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.