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.
1// Copyright (c) 2011 The LevelDB Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file. See the AUTHORS file for names of contributors.5#include <kcpolydb.h>6#include <stdio.h>7#include <stdlib.h>9#include "util/histogram.h"10#include "util/random.h"11#include "util/testutil.h"13// Comma-separated list of operations to run in the specified order14// Actual benchmarks:15//16// fillseq -- write N values in sequential key order in async mode17// fillrandom -- write N values in random key order in async mode18// overwrite -- overwrite N values in random key order in async mode19// fillseqsync -- write N/100 values in sequential key order in sync mode20// fillrandsync -- write N/100 values in random key order in sync mode21// fillrand100K -- write N/1000 100K values in random order in async mode22// fillseq100K -- write N/1000 100K values in seq order in async mode23// readseq -- read N times sequentially24// readseq100K -- read N/1000 100K values in sequential order in async mode25// readrand100K -- read N/1000 100K values in sequential order in async mode26// readrandom -- read N times in random order27static const char* FLAGS_benchmarks =28"fillseq,"29"fillseqsync,"30"fillrandsync,"31"fillrandom,"32"overwrite,"33"readrandom,"34"readseq,"35"fillrand100K,"36"fillseq100K,"37"readseq100K,"38"readrand100K,";40// Number of key/values to place in database41static int FLAGS_num = 1000000;43// Number of read operations to do. If negative, do FLAGS_num reads.44static int FLAGS_reads = -1;46// Size of each value47static int FLAGS_value_size = 100;49// Arrange to generate values that shrink to this fraction of50// their original size after compression51static double FLAGS_compression_ratio = 0.5;53// Print histogram of operation timings54static bool FLAGS_histogram = false;56// Cache size. Default 4 MB57static int FLAGS_cache_size = 4194304;59// Page size. Default 1 KB60static int FLAGS_page_size = 1024;62// If true, do not destroy the existing database. If you set this63// flag and also specify a benchmark that wants a fresh database, that64// benchmark will fail.65static bool FLAGS_use_existing_db = false;67// Compression flag. If true, compression is on. If false, compression68// is off.69static bool FLAGS_compression = true;71// Use the db with the following name.72static const char* FLAGS_db = nullptr;74inline static void DBSynchronize(kyotocabinet::TreeDB* db_) {75// Synchronize will flush writes to disk76if (!db_->synchronize()) {77fprintf(stderr, "synchronize error: %s\n", db_->error().name());78}79}81namespace leveldb {83// Helper for quickly generating random data.84namespace {85class RandomGenerator {86private:87std::string data_;88int pos_;90public:91RandomGenerator() {92// We use a limited amount of data over and over again and ensure93// that it is larger than the compression window (32KB), and also94// large enough to serve all typical value sizes we want to write.95Random rnd(301);96std::string piece;97while (data_.size() < 1048576) {98// Add a short fragment that is as compressible as specified99// by FLAGS_compression_ratio.100test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece);101data_.append(piece);102}103pos_ = 0;104}106Slice Generate(int len) {107if (pos_ + len > data_.size()) {108pos_ = 0;109assert(len < data_.size());110}111pos_ += len;112return Slice(data_.data() + pos_ - len, len);113}114};116static Slice TrimSpace(Slice s) {117int start = 0;118while (start < s.size() && isspace(s[start])) {119start++;120}121int limit = s.size();122while (limit > start && isspace(s[limit - 1])) {123limit--;124}125return Slice(s.data() + start, limit - start);126}128} // namespace130class Benchmark {131private:132kyotocabinet::TreeDB* db_;133int db_num_;134int num_;135int reads_;136double start_;137double last_op_finish_;138int64_t bytes_;139std::string message_;140Histogram hist_;141RandomGenerator gen_;142Random rand_;143kyotocabinet::LZOCompressor<kyotocabinet::LZO::RAW> comp_;145// State kept for progress messages146int done_;147int next_report_; // When to report next149void PrintHeader() {150const int kKeySize = 16;151PrintEnvironment();152fprintf(stdout, "Keys: %d bytes each\n", kKeySize);153fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n",154FLAGS_value_size,155static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));156fprintf(stdout, "Entries: %d\n", num_);157fprintf(stdout, "RawSize: %.1f MB (estimated)\n",158((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_) /1591048576.0));160fprintf(stdout, "FileSize: %.1f MB (estimated)\n",161(((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) /1621048576.0));163PrintWarnings();164fprintf(stdout, "------------------------------------------------\n");165}167void PrintWarnings() {168#if defined(__GNUC__) && !defined(__OPTIMIZE__)169fprintf(170stdout,171"WARNING: Optimization is disabled: benchmarks unnecessarily slow\n");172#endif173#ifndef NDEBUG174fprintf(stdout,175"WARNING: Assertions are enabled; benchmarks unnecessarily slow\n");176#endif177}179void PrintEnvironment() {180fprintf(stderr, "Kyoto Cabinet: version %s, lib ver %d, lib rev %d\n",181kyotocabinet::VERSION, kyotocabinet::LIBVER, kyotocabinet::LIBREV);183#if defined(__linux)184time_t now = time(nullptr);185fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline187FILE* cpuinfo = fopen("/proc/cpuinfo", "r");188if (cpuinfo != nullptr) {189char line[1000];190int num_cpus = 0;191std::string cpu_type;192std::string cache_size;193while (fgets(line, sizeof(line), cpuinfo) != nullptr) {194const char* sep = strchr(line, ':');195if (sep == nullptr) {196continue;197}198Slice key = TrimSpace(Slice(line, sep - 1 - line));199Slice val = TrimSpace(Slice(sep + 1));200if (key == "model name") {201++num_cpus;202cpu_type = val.ToString();203} else if (key == "cache size") {204cache_size = val.ToString();205}206}207fclose(cpuinfo);208fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str());209fprintf(stderr, "CPUCache: %s\n", cache_size.c_str());210}211#endif212}214void Start() {215start_ = Env::Default()->NowMicros() * 1e-6;216bytes_ = 0;217message_.clear();218last_op_finish_ = start_;219hist_.Clear();220done_ = 0;221next_report_ = 100;222}224void FinishedSingleOp() {225if (FLAGS_histogram) {226double now = Env::Default()->NowMicros() * 1e-6;227double micros = (now - last_op_finish_) * 1e6;228hist_.Add(micros);229if (micros > 20000) {230fprintf(stderr, "long op: %.1f micros%30s\r", micros, "");231fflush(stderr);232}233last_op_finish_ = now;234}236done_++;237if (done_ >= next_report_) {238if (next_report_ < 1000)239next_report_ += 100;240else if (next_report_ < 5000)241next_report_ += 500;242else if (next_report_ < 10000)243next_report_ += 1000;244else if (next_report_ < 50000)245next_report_ += 5000;246else if (next_report_ < 100000)247next_report_ += 10000;248else if (next_report_ < 500000)249next_report_ += 50000;250else
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.