summaryrefslogtreecommitdiffstats
path: root/src/test/kv_store_bench.h
blob: 689c769ce5290ce57221ff313d5078f16e1f2fac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
 * Benchmarking suite for key-value store
 *
 * September 2, 2012
 * Eleanor Cawthon
 * eleanor.cawthon@inktank.com
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 */

#ifndef KVSTOREBENCH_H_
#define KVSTOREBENCH_H_

#include "key_value_store/key_value_structure.h"
#include "key_value_store/kv_flat_btree_async.h"
#include "common/Clock.h"
#include "global/global_context.h"
#include "common/Cond.h"

#include <string>
#include <climits>
#include <cfloat>
#include <iostream>

/**
 * stores pairings from op type to time taken for that op (for latency), and to
 * time that op completed to the nearest second (for throughput).
 */
struct kv_bench_data {
  JSONFormatter throughput_jf;

  JSONFormatter latency_jf;
};

class KvStoreBench;

/**
 * keeps track of the number of milliseconds between two events - used to
 * measure latency
 */
struct StopWatch {
  utime_t begin_time;
  utime_t end_time;

  void start_time() {
    begin_time = ceph_clock_now();
  }
  void stop_time() {
    end_time = ceph_clock_now();
  }
  double get_time() {
    return (end_time - begin_time) * 1000;
  }
  void clear() {
    begin_time = end_time = utime_t();
  }
};

/**
 * arguments passed to the callback method when the op is being timed
 */
struct timed_args {
  StopWatch sw;
  //kv_bench_data data;
  KvStoreBench * kvsb;
  ceph::buffer::list val;
  int err;
  char op;

  timed_args ()
  : kvsb(NULL),
    err(0),
    op(' ')
  {};

  timed_args (KvStoreBench * k)
  : kvsb(k),
    err(0),
    op(' ')
  {}
};

typedef std::pair<std::string, ceph::buffer::list> (KvStoreBench::*next_gen_t)(bool new_elem);

class KvStoreBench {

protected:

  //test setup variables set from command line
  int entries; //the number of entries to write initially
  int ops; //the number of operations to time
  int clients; //the total number of clients running this test - used
	       //in the aio test to coordinate the end of the initial sets
  int key_size;//number of characters in keys to write
  int val_size;//number of characters in values to write
  int max_ops_in_flight;
  bool clear_first;//if true, remove all objects in pool before starting tests

  //variables passed to KeyValueStructure
  int k;
  int cache_size; //number of index entries to store in cache
  double cache_refresh; //cache_size / cache_refresh entries are read each time
			//the index is read
  std::string client_name;
  bool verbose;//if true, display debug output

  //internal
  std::map<int, char> probs;//map of numbers from 1 to 100 to chars representing
			//operation types - used to generate random operations
  std::set<std::string> key_set;//set of keys already in the data set
  KeyValueStructure * kvs;
  kv_bench_data data;//stores throughput and latency from completed tests
  ceph::mutex data_lock = ceph::make_mutex("data lock");
  ceph::condition_variable op_avail; // signaled when an op completes
  int ops_in_flight;//number of operations currently in progress
  ceph::mutex ops_in_flight_lock =
    ceph::make_mutex("KvStoreBench::ops_in_flight_lock");
  //these are used for cleanup and setup purposes - they are NOT passed to kvs!
  librados::Rados rados;
  std::string rados_id;
  std::string pool_name;
  bool io_ctx_ready;
  librados::IoCtx io_ctx;

  /**
   * Prints JSON-formatted throughput and latency data.
   *
   * Throughput data is {'char representing the operation type':time the op
   * completed to the nearest second}
   * Latency is {'char representing the operation type':time taken by the op}
   */
  void print_time_data();

public:

  KvStoreBench();

  //after this is called, objects created by the KeyValueStructure remain.
  ~KvStoreBench();

  /**
   * parses command line arguments, sets up this rados instance, clears the
   * pool if clear_first is true and calls kvs->setup.
   */
  int setup(int argc, const char** argv);

  /**
   * Returns a string of random characters of length len
   */
  std::string random_string(int len);

  /**
   * Inserts entries random keys and values asynchronously.
   */
  int test_random_insertions();

  /**
   * calls test_random_insertions, then does ops randomly chosen operations
   * asynchronously, with max_ops_in_flight operations at a time.
   */
  int test_teuthology_aio(next_gen_t distr, const std::map<int, char> &probs);

  /**
   * calls test_random_insertions, then does ops randomly chosen operations
   * synchronously.
   */
  int test_teuthology_sync(next_gen_t distr, const std::map<int, char> &probs);

  /**
   * returns a key-value pair. If new_elem is true, the key is randomly
   * generated. If it is false, the key is selected from the keys currently in
   * the key set.
   */
  std::pair<std::string, ceph::buffer::list> rand_distr(bool new_elem);

  /**
   * Called when aio operations complete. Updates data.
   */
  static void aio_callback_timed(int * err, void *arg);

  /**
   * Calls test_ methods. Change to call, for example, multiple runs of a test
   * with different settings. Currently just calls test_teuthology_aio.
   */
  int teuthology_tests();

};

#endif /* KVSTOREBENCH_H_ */