Skip to content

Commit 40ddc3d

Browse files
author
Feng Zhu
committed
add cache bench
Summary: 1. A benchmark for cache Test Plan: ./cache_bench Reviewers: yhchiang, dhruba, sdong, igor, ljin Reviewed By: ljin Subscribers: leveldb Differential Revision: https://reviews.facebook.net/D22809
1 parent 9f1c80b commit 40ddc3d

File tree

2 files changed

+261
-1
lines changed

2 files changed

+261
-1
lines changed

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ TOOLS = \
132132
options_test \
133133
blob_store_bench
134134

135-
PROGRAMS = db_bench signal_test table_reader_bench log_and_apply_bench $(TOOLS)
135+
PROGRAMS = db_bench signal_test table_reader_bench log_and_apply_bench cache_bench $(TOOLS)
136136

137137
# The library name is configurable since we are maintaining libraries of both
138138
# debug/release mode.
@@ -264,6 +264,9 @@ $(LIBRARY): $(LIBOBJECTS)
264264
db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL)
265265
$(CXX) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
266266

267+
cache_bench: util/cache_bench.o $(LIBOBJECTS) $(TESTUTIL)
268+
$(CXX) util/cache_bench.o $(LIBOBJECTS) $(TESTUTIL) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
269+
267270
block_hash_index_test: table/block_hash_index_test.o $(LIBOBJECTS) $(TESTHARNESS)
268271
$(CXX) table/block_hash_index_test.o $(LIBOBJECTS) $(TESTHARNESS) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
269272

util/cache_bench.cc

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
2+
// This source code is licensed under the BSD-style license found in the
3+
// LICENSE file in the root directory of this source tree. An additional grant
4+
// of patent rights can be found in the PATENTS file in the same directory.
5+
6+
#ifndef __STDC_FORMAT_MACROS
7+
#define __STDC_FORMAT_MACROS
8+
#endif
9+
#ifndef GFLAGS
10+
#include <cstdio>
11+
int main() {
12+
fprintf(stderr, "Please install gflags to run rocksdb tools\n");
13+
return 1;
14+
}
15+
#else
16+
17+
#include <sys/types.h>
18+
#include <stdio.h>
19+
#include <gflags/gflags.h>
20+
21+
#include "rocksdb/db.h"
22+
#include "rocksdb/cache.h"
23+
#include "rocksdb/env.h"
24+
#include "port/port.h"
25+
#include "util/mutexlock.h"
26+
#include "util/random.h"
27+
28+
using GFLAGS::ParseCommandLineFlags;
29+
30+
static const uint32_t KB = 1024;
31+
32+
DEFINE_int32(threads, 10, "Number of concurrent threads to run.");
33+
DEFINE_int64(cache_size, 2 * KB * KB * KB,
34+
"Number of bytes to use as a cache of uncompressed data.");
35+
DEFINE_int32(num_shard_bits, 4, "shard_bits.");
36+
37+
DEFINE_int64(max_key, 1 * KB* KB, "Max number of key to place in cache");
38+
DEFINE_uint64(ops_per_thread, 1200000, "Number of operations per thread.");
39+
40+
DEFINE_int32(insert_percent, 40,
41+
"Ratio of insert to total workload (expressed as a percentage)");
42+
DEFINE_int32(lookup_percent, 50,
43+
"Ratio of lookup to total workload (expressed as a percentage)");
44+
DEFINE_int32(erase_percent, 10,
45+
"Ratio of erase to total workload (expressed as a percentage)");
46+
47+
namespace rocksdb {
48+
49+
class CacheBench;
50+
namespace {
51+
void deleter(const Slice& key, void* value) {
52+
delete reinterpret_cast<char *>(value);
53+
}
54+
55+
// State shared by all concurrent executions of the same benchmark.
56+
class SharedState {
57+
public:
58+
explicit SharedState(CacheBench* cache_bench)
59+
: cv_(&mu_),
60+
num_threads_(FLAGS_threads),
61+
num_initialized_(0),
62+
start_(false),
63+
num_done_(0),
64+
cache_bench_(cache_bench) {
65+
}
66+
67+
~SharedState() {}
68+
69+
port::Mutex* GetMutex() {
70+
return &mu_;
71+
}
72+
73+
port::CondVar* GetCondVar() {
74+
return &cv_;
75+
}
76+
77+
CacheBench* GetCacheBench() const {
78+
return cache_bench_;
79+
}
80+
81+
void IncInitialized() {
82+
num_initialized_++;
83+
}
84+
85+
void IncDone() {
86+
num_done_++;
87+
}
88+
89+
bool AllInitialized() const {
90+
return num_initialized_ >= num_threads_;
91+
}
92+
93+
bool AllDone() const {
94+
return num_done_ >= num_threads_;
95+
}
96+
97+
void SetStart() {
98+
start_ = true;
99+
}
100+
101+
bool Started() const {
102+
return start_;
103+
}
104+
105+
private:
106+
port::Mutex mu_;
107+
port::CondVar cv_;
108+
109+
const uint64_t num_threads_;
110+
uint64_t num_initialized_;
111+
bool start_;
112+
uint64_t num_done_;
113+
114+
CacheBench* cache_bench_;
115+
};
116+
117+
// Per-thread state for concurrent executions of the same benchmark.
118+
struct ThreadState {
119+
uint32_t tid;
120+
Random rnd;
121+
SharedState* shared;
122+
123+
ThreadState(uint32_t index, SharedState *shared)
124+
: tid(index),
125+
rnd(1000 + index),
126+
shared(shared) {}
127+
};
128+
} // namespace
129+
130+
class CacheBench {
131+
public:
132+
CacheBench() :
133+
cache_(NewLRUCache(FLAGS_cache_size, FLAGS_num_shard_bits)),
134+
num_threads_(FLAGS_threads) {}
135+
136+
~CacheBench() {}
137+
138+
bool Run() {
139+
rocksdb::Env* env = rocksdb::Env::Default();
140+
141+
PrintEnv();
142+
SharedState shared(this);
143+
std::vector<ThreadState*> threads(num_threads_);
144+
for (uint32_t i = 0; i < num_threads_; i++) {
145+
threads[i] = new ThreadState(i, &shared);
146+
env->StartThread(ThreadBody, threads[i]);
147+
}
148+
{
149+
MutexLock l(shared.GetMutex());
150+
while (!shared.AllInitialized()) {
151+
shared.GetCondVar()->Wait();
152+
}
153+
// Record start time
154+
uint64_t start_time = env->NowMicros();
155+
156+
// Start all threads
157+
shared.SetStart();
158+
shared.GetCondVar()->SignalAll();
159+
160+
// Wait threads to complete
161+
while (!shared.AllDone()) {
162+
shared.GetCondVar()->Wait();
163+
}
164+
165+
// Record end time
166+
uint64_t end_time = env->NowMicros();
167+
fprintf(stdout, "Complete in %" PRIu64 "ms\n", end_time - start_time);
168+
}
169+
return true;
170+
}
171+
172+
private:
173+
std::shared_ptr<Cache> cache_;
174+
uint32_t num_threads_;
175+
176+
static void ThreadBody(void* v) {
177+
ThreadState* thread = reinterpret_cast<ThreadState*>(v);
178+
SharedState* shared = thread->shared;
179+
180+
{
181+
MutexLock l(shared->GetMutex());
182+
shared->IncInitialized();
183+
if (shared->AllInitialized()) {
184+
shared->GetCondVar()->SignalAll();
185+
}
186+
while (!shared->Started()) {
187+
shared->GetCondVar()->Wait();
188+
}
189+
}
190+
thread->shared->GetCacheBench()->OperateCache(thread);
191+
192+
{
193+
MutexLock l(shared->GetMutex());
194+
shared->IncDone();
195+
if (shared->AllDone()) {
196+
shared->GetCondVar()->SignalAll();
197+
}
198+
}
199+
}
200+
201+
void OperateCache(ThreadState* thread) {
202+
for (uint64_t i = 0; i < FLAGS_ops_per_thread; i++) {
203+
uint64_t rand_key = thread->rnd.Next() % FLAGS_max_key;
204+
// Cast uint64* to be char*, data would be copied to cache
205+
Slice key(reinterpret_cast<char*>(&rand_key), 8);
206+
int32_t prob_op = thread->rnd.Uniform(100);
207+
if (prob_op >= 0 && prob_op < FLAGS_insert_percent) {
208+
// do insert
209+
auto handle = cache_->Insert(key, new char[10], 1, &deleter);
210+
cache_->Release(handle);
211+
} else if (prob_op -= FLAGS_insert_percent &&
212+
prob_op < FLAGS_lookup_percent) {
213+
// do lookup
214+
auto handle = cache_->Lookup(key);
215+
if (handle) {
216+
cache_->Release(handle);
217+
}
218+
} else if (prob_op -= FLAGS_lookup_percent &&
219+
prob_op < FLAGS_erase_percent) {
220+
// do erase
221+
cache_->Erase(key);
222+
}
223+
}
224+
}
225+
226+
void PrintEnv() const {
227+
printf("RocksDB version : %d.%d\n", kMajorVersion, kMinorVersion);
228+
printf("Number of threads : %d\n", FLAGS_threads);
229+
printf("Ops per thread : %" PRIu64 "\n", FLAGS_ops_per_thread);
230+
printf("Cache size : %" PRIu64 "\n", FLAGS_cache_size);
231+
printf("Num shard bits : %d\n", FLAGS_num_shard_bits);
232+
printf("Max key : %" PRIu64 "\n", FLAGS_max_key);
233+
printf("Insert percentage : %d%%\n", FLAGS_insert_percent);
234+
printf("Lookup percentage : %d%%\n", FLAGS_lookup_percent);
235+
printf("Erase percentage : %d%%\n", FLAGS_erase_percent);
236+
printf("----------------------------\n");
237+
}
238+
};
239+
} // namespace rocksdb
240+
241+
int main(int argc, char** argv) {
242+
ParseCommandLineFlags(&argc, &argv, true);
243+
244+
if (FLAGS_threads <= 0) {
245+
fprintf(stderr, "threads number <= 0\n");
246+
exit(1);
247+
}
248+
249+
rocksdb::CacheBench bench;
250+
if (bench.Run()) {
251+
return 0;
252+
} else {
253+
return 1;
254+
}
255+
}
256+
257+
#endif // GFLAGS

0 commit comments

Comments
 (0)