]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/cache/cache_bench.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
9 fprintf(stderr
, "Please install gflags to run rocksdb tools\n");
15 #include <sys/types.h>
18 #include "port/port.h"
19 #include "rocksdb/cache.h"
20 #include "rocksdb/db.h"
21 #include "rocksdb/env.h"
22 #include "util/gflags_compat.h"
23 #include "util/mutexlock.h"
24 #include "util/random.h"
26 using GFLAGS_NAMESPACE::ParseCommandLineFlags
;
28 static const uint32_t KB
= 1024;
30 DEFINE_int32(threads
, 16, "Number of concurrent threads to run.");
31 DEFINE_int64(cache_size
, 8 * KB
* KB
,
32 "Number of bytes to use as a cache of uncompressed data.");
33 DEFINE_int32(num_shard_bits
, 4, "shard_bits.");
35 DEFINE_int64(max_key
, 1 * KB
* KB
* KB
, "Max number of key to place in cache");
36 DEFINE_uint64(ops_per_thread
, 1200000, "Number of operations per thread.");
38 DEFINE_bool(populate_cache
, false, "Populate cache before operations");
39 DEFINE_int32(insert_percent
, 40,
40 "Ratio of insert to total workload (expressed as a percentage)");
41 DEFINE_int32(lookup_percent
, 50,
42 "Ratio of lookup to total workload (expressed as a percentage)");
43 DEFINE_int32(erase_percent
, 10,
44 "Ratio of erase to total workload (expressed as a percentage)");
46 DEFINE_bool(use_clock_cache
, false, "");
48 namespace ROCKSDB_NAMESPACE
{
52 void deleter(const Slice
& /*key*/, void* value
) {
53 delete reinterpret_cast<char *>(value
);
56 // State shared by all concurrent executions of the same benchmark.
59 explicit SharedState(CacheBench
* cache_bench
)
61 num_threads_(FLAGS_threads
),
65 cache_bench_(cache_bench
) {
70 port::Mutex
* GetMutex() {
74 port::CondVar
* GetCondVar() {
78 CacheBench
* GetCacheBench() const {
82 void IncInitialized() {
90 bool AllInitialized() const {
91 return num_initialized_
>= num_threads_
;
94 bool AllDone() const {
95 return num_done_
>= num_threads_
;
102 bool Started() const {
110 const uint64_t num_threads_
;
111 uint64_t num_initialized_
;
115 CacheBench
* cache_bench_
;
118 // Per-thread state for concurrent executions of the same benchmark.
124 ThreadState(uint32_t index
, SharedState
* _shared
)
125 : tid(index
), rnd(1000 + index
), shared(_shared
) {}
131 CacheBench() : num_threads_(FLAGS_threads
) {
132 if (FLAGS_use_clock_cache
) {
133 cache_
= NewClockCache(FLAGS_cache_size
, FLAGS_num_shard_bits
);
135 fprintf(stderr
, "Clock cache not supported.\n");
139 cache_
= NewLRUCache(FLAGS_cache_size
, FLAGS_num_shard_bits
);
145 void PopulateCache() {
147 for (int64_t i
= 0; i
< FLAGS_cache_size
; i
++) {
148 uint64_t rand_key
= rnd
.Next() % FLAGS_max_key
;
149 // Cast uint64* to be char*, data would be copied to cache
150 Slice
key(reinterpret_cast<char*>(&rand_key
), 8);
152 cache_
->Insert(key
, new char[10], 1, &deleter
);
157 ROCKSDB_NAMESPACE::Env
* env
= ROCKSDB_NAMESPACE::Env::Default();
160 SharedState
shared(this);
161 std::vector
<ThreadState
*> threads(num_threads_
);
162 for (uint32_t i
= 0; i
< num_threads_
; i
++) {
163 threads
[i
] = new ThreadState(i
, &shared
);
164 env
->StartThread(ThreadBody
, threads
[i
]);
167 MutexLock
l(shared
.GetMutex());
168 while (!shared
.AllInitialized()) {
169 shared
.GetCondVar()->Wait();
172 uint64_t start_time
= env
->NowMicros();
176 shared
.GetCondVar()->SignalAll();
178 // Wait threads to complete
179 while (!shared
.AllDone()) {
180 shared
.GetCondVar()->Wait();
184 uint64_t end_time
= env
->NowMicros();
185 double elapsed
= static_cast<double>(end_time
- start_time
) * 1e-6;
186 uint32_t qps
= static_cast<uint32_t>(
187 static_cast<double>(FLAGS_threads
* FLAGS_ops_per_thread
) / elapsed
);
188 fprintf(stdout
, "Complete in %.3f s; QPS = %u\n", elapsed
, qps
);
194 std::shared_ptr
<Cache
> cache_
;
195 uint32_t num_threads_
;
197 static void ThreadBody(void* v
) {
198 ThreadState
* thread
= reinterpret_cast<ThreadState
*>(v
);
199 SharedState
* shared
= thread
->shared
;
202 MutexLock
l(shared
->GetMutex());
203 shared
->IncInitialized();
204 if (shared
->AllInitialized()) {
205 shared
->GetCondVar()->SignalAll();
207 while (!shared
->Started()) {
208 shared
->GetCondVar()->Wait();
211 thread
->shared
->GetCacheBench()->OperateCache(thread
);
214 MutexLock
l(shared
->GetMutex());
216 if (shared
->AllDone()) {
217 shared
->GetCondVar()->SignalAll();
222 void OperateCache(ThreadState
* thread
) {
223 for (uint64_t i
= 0; i
< FLAGS_ops_per_thread
; i
++) {
224 uint64_t rand_key
= thread
->rnd
.Next() % FLAGS_max_key
;
225 // Cast uint64* to be char*, data would be copied to cache
226 Slice
key(reinterpret_cast<char*>(&rand_key
), 8);
227 int32_t prob_op
= thread
->rnd
.Uniform(100);
228 if (prob_op
>= 0 && prob_op
< FLAGS_insert_percent
) {
230 cache_
->Insert(key
, new char[10], 1, &deleter
);
231 } else if (prob_op
-= FLAGS_insert_percent
&&
232 prob_op
< FLAGS_lookup_percent
) {
234 auto handle
= cache_
->Lookup(key
);
236 cache_
->Release(handle
);
238 } else if (prob_op
-= FLAGS_lookup_percent
&&
239 prob_op
< FLAGS_erase_percent
) {
246 void PrintEnv() const {
247 printf("RocksDB version : %d.%d\n", kMajorVersion
, kMinorVersion
);
248 printf("Number of threads : %d\n", FLAGS_threads
);
249 printf("Ops per thread : %" PRIu64
"\n", FLAGS_ops_per_thread
);
250 printf("Cache size : %" PRIu64
"\n", FLAGS_cache_size
);
251 printf("Num shard bits : %d\n", FLAGS_num_shard_bits
);
252 printf("Max key : %" PRIu64
"\n", FLAGS_max_key
);
253 printf("Populate cache : %d\n", FLAGS_populate_cache
);
254 printf("Insert percentage : %d%%\n", FLAGS_insert_percent
);
255 printf("Lookup percentage : %d%%\n", FLAGS_lookup_percent
);
256 printf("Erase percentage : %d%%\n", FLAGS_erase_percent
);
257 printf("----------------------------\n");
260 } // namespace ROCKSDB_NAMESPACE
262 int main(int argc
, char** argv
) {
263 ParseCommandLineFlags(&argc
, &argv
, true);
265 if (FLAGS_threads
<= 0) {
266 fprintf(stderr
, "threads number <= 0\n");
270 ROCKSDB_NAMESPACE::CacheBench bench
;
271 if (FLAGS_populate_cache
) {
272 bench
.PopulateCache();