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.
252void Report(const Slice& name) {253// Pretend at least one op was done in case we are running a benchmark254// that does not call FinishedSingleOp().255if (done_ < 1) done_ = 1;257std::string extra;258if (bytes_ > 0) {259// Rate is computed on actual elapsed time, not the sum of per-thread260// elapsed times.261double elapsed = (finish_ - start_) * 1e-6;262char rate[100];263snprintf(rate, sizeof(rate), "%6.1f MB/s",264(bytes_ / 1048576.0) / elapsed);265extra = rate;266}267AppendWithSpace(&extra, message_);269fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", name.ToString().c_str(),270seconds_ * 1e6 / done_, (extra.empty() ? "" : " "), extra.c_str());271if (FLAGS_histogram) {272fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());273}274fflush(stdout);275}276};278// State shared by all concurrent executions of the same benchmark.279struct SharedState {280port::Mutex mu;281port::CondVar cv GUARDED_BY(mu);282int total GUARDED_BY(mu);284// Each thread goes through the following states:285// (1) initializing286// (2) waiting for others to be initialized287// (3) running288// (4) done290int num_initialized GUARDED_BY(mu);291int num_done GUARDED_BY(mu);292bool start GUARDED_BY(mu);294SharedState(int total)295: cv(&mu), total(total), num_initialized(0), num_done(0), start(false) {}296};298// Per-thread state for concurrent executions of the same benchmark.299struct ThreadState {300int tid; // 0..n-1 when running in n threads301Random rand; // Has different seeds for different threads302Stats stats;303SharedState* shared;305ThreadState(int index) : tid(index), rand(1000 + index), shared(nullptr) {}306};308} // namespace310class Benchmark {311private:312Cache* cache_;313const FilterPolicy* filter_policy_;314DB* db_;315int num_;316int value_size_;317int entries_per_batch_;318WriteOptions write_options_;319int reads_;320int heap_counter_;322void PrintHeader() {323const int kKeySize = 16;324PrintEnvironment();325fprintf(stdout, "Keys: %d bytes each\n", kKeySize);326fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n",327FLAGS_value_size,328static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));329fprintf(stdout, "Entries: %d\n", num_);330fprintf(stdout, "RawSize: %.1f MB (estimated)\n",331((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /3321048576.0));333fprintf(stdout, "FileSize: %.1f MB (estimated)\n",334(((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) /3351048576.0));336PrintWarnings();337fprintf(stdout, "------------------------------------------------\n");338}340void PrintWarnings() {341#if defined(__GNUC__) && !defined(__OPTIMIZE__)342fprintf(343stdout,344"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");345#endif346#ifndef NDEBUG347fprintf(stdout,348"WARNING: Assertions are enabled; benchmarks unnecessarily slow\n");349#endif351// See if snappy is working by attempting to compress a compressible string352const char text[] = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";353std::string compressed;354if (!port::Snappy_Compress(text, sizeof(text), &compressed)) {355fprintf(stdout, "WARNING: Snappy compression is not enabled\n");356} else if (compressed.size() >= sizeof(text)) {357fprintf(stdout, "WARNING: Snappy compression is not effective\n");358}359}361void PrintEnvironment() {362fprintf(stderr, "LevelDB: version %d.%d\n", kMajorVersion,363kMinorVersion);365#if defined(__linux)366time_t now = time(nullptr);367fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline369FILE* cpuinfo = fopen("/proc/cpuinfo", "r");370if (cpuinfo != nullptr) {371char line[1000];372int num_cpus = 0;373std::string cpu_type;374std::string cache_size;375while (fgets(line, sizeof(line), cpuinfo) != nullptr) {376const char* sep = strchr(line, ':');377if (sep == nullptr) {378continue;379}380Slice key = TrimSpace(Slice(line, sep - 1 - line));381Slice val = TrimSpace(Slice(sep + 1));382if (key == "model name") {383++num_cpus;384cpu_type = val.ToString();385} else if (key == "cache size") {386cache_size = val.ToString();387}388}389fclose(cpuinfo);390fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str());391fprintf(stderr, "CPUCache: %s\n", cache_size.c_str());392}393#endif394}396public:397Benchmark()398: cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : nullptr),399filter_policy_(FLAGS_bloom_bits >= 0400? NewBloomFilterPolicy(FLAGS_bloom_bits)401: nullptr),402db_(nullptr),403num_(FLAGS_num),404value_size_(FLAGS_value_size),405entries_per_batch_(1),406reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),407heap_counter_(0) {408std::vector<std::string> files;409g_env->GetChildren(FLAGS_db, &files);410for (size_t i = 0; i < files.size(); i++) {411if (Slice(files[i]).starts_with("heap-")) {412g_env->DeleteFile(std::string(FLAGS_db) + "/" + files[i]);413}414}415if (!FLAGS_use_existing_db) {416DestroyDB(FLAGS_db, Options());417}418}420~Benchmark() {421delete db_;422delete cache_;423delete filter_policy_;424}426void Run() {427PrintHeader();428Open();430const char* benchmarks = FLAGS_benchmarks;431while (benchmarks != nullptr) {432const char* sep = strchr(benchmarks, ',');433Slice name;434if (sep == nullptr) {435name = benchmarks;436benchmarks = nullptr;437} else {438name = Slice(benchmarks, sep - benchmarks);439benchmarks = sep + 1;440}442// Reset parameters that may be overridden below443num_ = FLAGS_num;444reads_ = (FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads);445value_size_ = FLAGS_value_size;446entries_per_batch_ = 1;447write_options_ = WriteOptions();449void (Benchmark::*method)(ThreadState*) = nullptr;450bool fresh_db = false;451int num_threads = FLAGS_threads;453if (name == Slice("open")) {454method = &Benchmark::OpenBench;455num_ /= 10000;456if (num_ < 1) num_ = 1;457} else if (name == Slice("fillseq")) {458fresh_db = true;459method = &Benchmark::WriteSeq;460} else if (name == Slice("fillbatch")) {461fresh_db = true;462entries_per_batch_ = 1000;463method = &Benchmark::WriteSeq;464} else if (name == Slice("fillrandom")) {465fresh_db = true;466method = &Benchmark::WriteRandom;467} else if (name == Slice("overwrite")) {468fresh_db = false;469method = &Benchmark::WriteRandom;470} else if (name == Slice("fillsync")) {471fresh_db = true;472num_ /= 1000;473write_options_.sync = true;474method = &Benchmark::WriteRandom;475} else if (name == Slice("fill100K")) {476fresh_db = true;477num_ /= 1000;478value_size_ = 100 * 1000;479method = &Benchmark::WriteRandom;480} else if (name == Slice("readseq")) {481method = &Benchmark::ReadSequential;482} else if (name == Slice("readreverse")) {483method = &Benchmark::ReadReverse;484} else if (name == Slice("readrandom")) {485method = &Benchmark::ReadRandom;486} else if (name == Slice("readmissing")) {487method = &Benchmark::ReadMissing;488} else if (name == Slice("seekrandom")) {489method = &Benchmark::SeekRandom;490} else if (name == Slice("readhot")) {491method = &Benchmark::ReadHot;492} else if (name == Slice("readrandomsmall")) {493reads_ /= 1000;494method = &Benchmark::ReadRandom;495} else if (name == Slice("deleteseq")) {496method = &Benchmark::DeleteSeq;497} else if (name == Slice("deleterandom")) {498method = &Benchmark::DeleteRandom;499} else if (name == Slice("readwhilewriting")) {500num_threads++; // Add extra thread for writing
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.