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.
501method = &Benchmark::ReadWhileWriting;502} else if (name == Slice("compact")) {503method = &Benchmark::Compact;504} else if (name == Slice("crc32c")) {505method = &Benchmark::Crc32c;506} else if (name == Slice("snappycomp")) {507method = &Benchmark::SnappyCompress;508} else if (name == Slice("snappyuncomp")) {509method = &Benchmark::SnappyUncompress;510} else if (name == Slice("heapprofile")) {511HeapProfile();512} else if (name == Slice("stats")) {513PrintStats("leveldb.stats");514} else if (name == Slice("sstables")) {515PrintStats("leveldb.sstables");516} else {517if (!name.empty()) { // No error message for empty name518fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());519}520}522if (fresh_db) {523if (FLAGS_use_existing_db) {524fprintf(stdout, "%-12s : skipped (--use_existing_db is true)\n",525name.ToString().c_str());526method = nullptr;527} else {528delete db_;529db_ = nullptr;530DestroyDB(FLAGS_db, Options());531Open();532}533}535if (method != nullptr) {536RunBenchmark(num_threads, name, method);537}538}539}541private:542struct ThreadArg {543Benchmark* bm;544SharedState* shared;545ThreadState* thread;546void (Benchmark::*method)(ThreadState*);547};549static void ThreadBody(void* v) {550ThreadArg* arg = reinterpret_cast<ThreadArg*>(v);551SharedState* shared = arg->shared;552ThreadState* thread = arg->thread;553{554MutexLock l(&shared->mu);555shared->num_initialized++;556if (shared->num_initialized >= shared->total) {557shared->cv.SignalAll();558}559while (!shared->start) {560shared->cv.Wait();561}562}564thread->stats.Start();565(arg->bm->*(arg->method))(thread);566thread->stats.Stop();568{569MutexLock l(&shared->mu);570shared->num_done++;571if (shared->num_done >= shared->total) {572shared->cv.SignalAll();573}574}575}577void RunBenchmark(int n, Slice name,578void (Benchmark::*method)(ThreadState*)) {579SharedState shared(n);581ThreadArg* arg = new ThreadArg[n];582for (int i = 0; i < n; i++) {583arg[i].bm = this;584arg[i].method = method;585arg[i].shared = &shared;586arg[i].thread = new ThreadState(i);587arg[i].thread->shared = &shared;588g_env->StartThread(ThreadBody, &arg[i]);589}591shared.mu.Lock();592while (shared.num_initialized < n) {593shared.cv.Wait();594}596shared.start = true;597shared.cv.SignalAll();598while (shared.num_done < n) {599shared.cv.Wait();600}601shared.mu.Unlock();603for (int i = 1; i < n; i++) {604arg[0].thread->stats.Merge(arg[i].thread->stats);605}606arg[0].thread->stats.Report(name);608for (int i = 0; i < n; i++) {609delete arg[i].thread;610}611delete[] arg;612}614void Crc32c(ThreadState* thread) {615// Checksum about 500MB of data total616const int size = 4096;617const char* label = "(4K per op)";618std::string data(size, 'x');619int64_t bytes = 0;620uint32_t crc = 0;621while (bytes < 500 * 1048576) {622crc = crc32c::Value(data.data(), size);623thread->stats.FinishedSingleOp();624bytes += size;625}626// Print so result is not dead627fprintf(stderr, "... crc=0x%x\r", static_cast<unsigned int>(crc));629thread->stats.AddBytes(bytes);630thread->stats.AddMessage(label);631}633void SnappyCompress(ThreadState* thread) {634RandomGenerator gen;635Slice input = gen.Generate(Options().block_size);636int64_t bytes = 0;637int64_t produced = 0;638bool ok = true;639std::string compressed;640while (ok && bytes < 1024 * 1048576) { // Compress 1G641ok = port::Snappy_Compress(input.data(), input.size(), &compressed);642produced += compressed.size();643bytes += input.size();644thread->stats.FinishedSingleOp();645}647if (!ok) {648thread->stats.AddMessage("(snappy failure)");649} else {650char buf[100];651snprintf(buf, sizeof(buf), "(output: %.1f%%)",652(produced * 100.0) / bytes);653thread->stats.AddMessage(buf);654thread->stats.AddBytes(bytes);655}656}658void SnappyUncompress(ThreadState* thread) {659RandomGenerator gen;660Slice input = gen.Generate(Options().block_size);661std::string compressed;662bool ok = port::Snappy_Compress(input.data(), input.size(), &compressed);663int64_t bytes = 0;664char* uncompressed = new char[input.size()];665while (ok && bytes < 1024 * 1048576) { // Compress 1G666ok = port::Snappy_Uncompress(compressed.data(), compressed.size(),667uncompressed);668bytes += input.size();669thread->stats.FinishedSingleOp();670}671delete[] uncompressed;673if (!ok) {674thread->stats.AddMessage("(snappy failure)");675} else {676thread->stats.AddBytes(bytes);677}678}680void Open() {681assert(db_ == nullptr);682Options options;683options.env = g_env;684options.create_if_missing = !FLAGS_use_existing_db;685options.block_cache = cache_;686options.write_buffer_size = FLAGS_write_buffer_size;687options.max_file_size = FLAGS_max_file_size;688options.block_size = FLAGS_block_size;689options.max_open_files = FLAGS_open_files;690options.filter_policy = filter_policy_;691options.reuse_logs = FLAGS_reuse_logs;692Status s = DB::Open(options, FLAGS_db, &db_);693if (!s.ok()) {694fprintf(stderr, "open error: %s\n", s.ToString().c_str());695exit(1);696}697}699void OpenBench(ThreadState* thread) {700for (int i = 0; i < num_; i++) {701delete db_;702Open();703thread->stats.FinishedSingleOp();704}705}707void WriteSeq(ThreadState* thread) { DoWrite(thread, true); }709void WriteRandom(ThreadState* thread) { DoWrite(thread, false); }711void DoWrite(ThreadState* thread, bool seq) {712if (num_ != FLAGS_num) {713char msg[100];714snprintf(msg, sizeof(msg), "(%d ops)", num_);715thread->stats.AddMessage(msg);716}718RandomGenerator gen;719WriteBatch batch;720Status s;721int64_t bytes = 0;722for (int i = 0; i < num_; i += entries_per_batch_) {723batch.Clear();724for (int j = 0; j < entries_per_batch_; j++) {725const int k = seq ? i + j : (thread->rand.Next() % FLAGS_num);726char key[100];727snprintf(key, sizeof(key), "%016d", k);728batch.Put(key, gen.Generate(value_size_));729bytes += value_size_ + strlen(key);730thread->stats.FinishedSingleOp();731}732s = db_->Write(write_options_, &batch);733if (!s.ok()) {734fprintf(stderr, "put error: %s\n", s.ToString().c_str());735exit(1);736}737}738thread->stats.AddBytes(bytes);739}741void ReadSequential(ThreadState* thread) {742Iterator* iter = db_->NewIterator(ReadOptions());743int i = 0;744int64_t bytes = 0;745for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) {746bytes += iter->key().size() + iter->value().size();747thread->stats.FinishedSingleOp();748++i;749}750delete iter;
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.