12 #include <sys/sysinfo.h>
14 #include "../allocator.h"
15 #include "../stats_server.h"
16 #include "../btree_choice.h"
23 split_ws(const string &s)
27 copy(istream_iterator<string>(iss),
28 istream_iterator<string>(),
29 back_inserter<vector<string>>(r));
34 parse_memory_spec(const string &s)
38 if (x.back() == 'G') {
39 mult = static_cast<size_t>(1) << 30;
41 } else if (x.back() == 'M') {
42 mult = static_cast<size_t>(1) << 20;
44 } else if (x.back() == 'K') {
45 mult = static_cast<size_t>(1) << 10;
48 return strtoul(x.c_str(), nullptr, 10) * mult;
52 main(int argc, char **argv)
54 void (*test_fn)(const string &, const persistconfig &, int, char **) = NULL;
55 string bench_type = "ycsb";
56 string db_type = "ndb-proto2";
57 char *curdir = get_current_dir_name();
58 string basedir = curdir;
60 size_t numa_memory = 0;
64 string stats_server_sockfile;
66 static struct option long_options[] =
68 {"verbose" , no_argument , &verbose , 1} ,
69 {"parallel-loading" , no_argument , &enable_parallel_loading , 1} ,
70 {"pin-cpus" , no_argument , &pin_cpus , 1} ,
71 {"slow-exit" , no_argument , &slow_exit , 1} ,
72 {"retry-aborted-transactions" , no_argument , &retry_aborted_transaction , 1} ,
73 {"backoff-aborted-transactions" , no_argument , &backoff_aborted_transaction , 1} ,
74 {"bench" , required_argument , 0 , 'b'} ,
75 {"scale-factor" , required_argument , 0 , 's'} ,
76 {"num-threads" , required_argument , 0 , 't'} ,
77 {"db-type" , required_argument , 0 , 'd'} ,
78 {"basedir" , required_argument , 0 , 'B'} ,
79 {"txn-flags" , required_argument , 0 , 'f'} ,
80 {"runtime" , required_argument , 0 , 'r'} ,
81 {"ops-per-worker" , required_argument , 0 , 'n'} ,
82 {"bench-opts" , required_argument , 0 , 'o'} ,
83 {"numa-memory" , required_argument , 0 , 'm'} , // implies --pin-cpus
84 {"logfile" , required_argument , 0 , 'l'} ,
85 {"assignment" , required_argument , 0 , 'a'} ,
86 {"log-nofsync" , no_argument , &cfg.nofsync_ , 1} ,
87 {"log-compress" , no_argument , &cfg.do_compress_ , 1} ,
88 {"log-fake-writes" , no_argument , &cfg.fake_writes_ , 1} ,
89 {"disable-gc" , no_argument , &cfg.disable_gc_ , 1} ,
90 {"disable-snapshots" , no_argument , &cfg.disable_snapshots_ , 1} ,
91 {"stats-server-sockfile" , required_argument , 0 , 'x'} ,
92 {"no-reset-counters" , no_argument , &no_reset_counters , 1} ,
96 int c = getopt_long(argc, argv, "b:s:t:d:B:f:r:n:o:m:l:a:x:", long_options, &option_index);
102 if (long_options[option_index].flag != 0)
112 scale_factor = strtod(optarg, NULL);
113 ALWAYS_ASSERT(scale_factor > 0.0);
117 nthreads = strtoul(optarg, NULL, 10);
118 ALWAYS_ASSERT(nthreads > 0);
130 txn_flags = strtoul(optarg, NULL, 10);
134 ALWAYS_ASSERT(!saw_run_spec);
136 runtime = strtoul(optarg, NULL, 10);
137 ALWAYS_ASSERT(runtime > 0);
138 run_mode = RUNMODE_TIME;
142 ALWAYS_ASSERT(!saw_run_spec);
144 ops_per_worker = strtoul(optarg, NULL, 10);
145 ALWAYS_ASSERT(ops_per_worker > 0);
146 run_mode = RUNMODE_OPS;
155 const size_t m = parse_memory_spec(optarg);
156 ALWAYS_ASSERT(m > 0);
162 cfg.logfiles_.emplace_back(optarg);
166 cfg.assignments_.emplace_back(
167 ParseCSVString<unsigned, RangeAwareParser<unsigned>>(optarg));
171 stats_server_sockfile = optarg;
175 /* getopt_long already printed an error message. */
183 if (bench_type == "tpcc")
184 test_fn = tpcc_do_test;
186 ALWAYS_ASSERT(false);
188 if (cfg.do_compress_ && cfg.logfiles_.empty()) {
189 cerr << "[ERROR] --log-compress specified without logging enabled" << endl;
193 if (cfg.fake_writes_ && cfg.logfiles_.empty()) {
194 cerr << "[ERROR] --log-fake-writes specified without logging enabled" << endl;
198 if (cfg.nofsync_ && cfg.logfiles_.empty()) {
199 cerr << "[ERROR] --log-nofsync specified without logging enabled" << endl;
203 if (cfg.fake_writes_ && cfg.nofsync_) {
204 cerr << "[WARNING] --log-nofsync has no effect with --log-fake-writes enabled" << endl;
207 #ifndef ENABLE_EVENT_COUNTERS
208 if (!stats_server_sockfile.empty()) {
209 cerr << "[WARNING] --stats-server-sockfile with no event counters enabled is useless" << endl;
213 // initialize the numa allocator
214 if (numa_memory > 0) {
215 const size_t maxpercpu = iceil(
216 numa_memory / nthreads, ::allocator::GetHugepageSize());
217 numa_memory = maxpercpu * nthreads;
218 ::allocator::Initialize(nthreads, maxpercpu);
221 const set<string> can_persist({"ndb-proto2"});
222 if (!cfg.logfiles_.empty() && !can_persist.count(db_type)) {
223 cerr << "[ERROR] benchmark " << db_type
224 << " does not have persistence implemented" << endl;
228 #ifdef PROTO2_CAN_DISABLE_GC
229 const set<string> has_gc({"ndb-proto1", "ndb-proto2"});
230 if (cfg.disable_gc_ && !has_gc.count(db_type)) {
231 cerr << "[ERROR] benchmark " << db_type
232 << " does not have gc to disable" << endl;
236 if (cfg.disable_gc_) {
237 cerr << "[ERROR] macro PROTO2_CAN_DISABLE_GC was not set, cannot disable gc" << endl;
242 #ifdef PROTO2_CAN_DISABLE_SNAPSHOTS
243 const set<string> has_snapshots({"ndb-proto2"});
244 if (cfg.disable_snapshots_ && !has_snapshots.count(db_type)) {
245 cerr << "[ERROR] benchmark " << db_type
246 << " does not have snapshots to disable" << endl;
250 if (cfg.disable_snapshots_) {
251 cerr << "[ERROR] macro PROTO2_CAN_DISABLE_SNAPSHOTS was not set, cannot disable snapshots" << endl;
255 #ifdef CHECK_INVARIANTS
256 cerr << "WARNING: invariant checking is enabled - should disable for benchmark" << endl;
257 #ifdef PARANOID_CHECKING
258 cerr << " *** Paranoid checking is enabled ***" << endl;
263 const unsigned long ncpus = coreid::num_cpus_online();
264 cerr << "Database Benchmark:" << endl;
265 cerr << " pid: " << getpid() << endl;
266 cerr << "settings:" << endl;
267 cerr << " par-loading : " << enable_parallel_loading << endl;
268 cerr << " pin-cpus : " << pin_cpus << endl;
269 cerr << " slow-exit : " << slow_exit << endl;
270 cerr << " retry-txns : " << retry_aborted_transaction << endl;
271 cerr << " backoff-txns: " << backoff_aborted_transaction << endl;
272 cerr << " bench : " << bench_type << endl;
273 cerr << " scale : " << scale_factor << endl;
274 cerr << " num-cpus : " << ncpus << endl;
275 cerr << " num-threads : " << nthreads << endl;
276 cerr << " db-type : " << db_type << endl;
277 cerr << " basedir : " << basedir << endl;
278 cerr << " txn-flags : " << hexify(txn_flags) << endl;
279 if (run_mode == RUNMODE_TIME)
280 cerr << " runtime : " << runtime << endl;
282 cerr << " ops/worker : " << ops_per_worker << endl;
283 #ifdef USE_VARINT_ENCODING
284 cerr << " var-encode : yes" << endl;
286 cerr << " var-encode : no" << endl;
290 cerr << " allocator : jemalloc" << endl;
291 #elif defined USE_TCMALLOC
292 cerr << " allocator : tcmalloc" << endl;
293 #elif defined USE_FLOW
294 cerr << " allocator : flow" << endl;
296 cerr << " allocator : libc" << endl;
298 if (numa_memory > 0) {
299 cerr << " numa-memory : " << numa_memory << endl;
301 cerr << " numa-memory : disabled" << endl;
303 cerr << " logfiles : " << cfg.logfiles_ << endl;
304 cerr << " assignments : " << cfg.assignments_ << endl;
305 cerr << " disable-gc : " << cfg.disable_gc_ << endl;
306 cerr << " disable-snapshots : " << cfg.disable_snapshots_ << endl;
307 cerr << " stats-server-sockfile: " << stats_server_sockfile << endl;
309 cerr << "system properties:" << endl;
310 cerr << " btree_internal_node_size: " << concurrent_btree::InternalNodeSize() << endl;
311 cerr << " btree_leaf_node_size : " << concurrent_btree::LeafNodeSize() << endl;
313 #ifdef TUPLE_PREFETCH
314 cerr << " tuple_prefetch : yes" << endl;
316 cerr << " tuple_prefetch : no" << endl;
319 #ifdef BTREE_NODE_PREFETCH
320 cerr << " btree_node_prefetch : yes" << endl;
322 cerr << " btree_node_prefetch : no" << endl;
327 if (!stats_server_sockfile.empty()) {
328 stats_server *srvr = new stats_server(stats_server_sockfile);
329 thread(&stats_server::serve_forever, srvr).detach();
332 vector<string> bench_toks = split_ws(bench_opts);
333 int argc = 1 + bench_toks.size();
335 argv[0] = (char *) bench_type.c_str();
336 for (size_t i = 1; i <= bench_toks.size(); i++)
337 argv[i] = (char *) bench_toks[i - 1].c_str();
338 test_fn(db_type, cfg, argc, argv);