]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/objectstore/ObjectStoreTransactionBenchmark.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / objectstore / ObjectStoreTransactionBenchmark.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2014 UnitedStack <haomai@unitedstack.com>
7 *
8 * Author: Haomai Wang <haomaiwang@gmail.com>
9 *
10 * This is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License version 2.1, as published by the Free Software
13 * Foundation. See file COPYING.
14 *
15 */
16
17 #include <stdlib.h>
18 #include <stdint.h>
19 #include <string>
20 #include <iostream>
21
22 using namespace std;
23
24 #include "common/ceph_argparse.h"
25 #include "common/debug.h"
26 #include "common/Cycles.h"
27 #include "global/global_init.h"
28 #include "os/ObjectStore.h"
29
30 class Transaction {
31 private:
32 ObjectStore::Transaction t;
33
34 public:
35 struct Tick {
36 uint64_t ticks;
37 uint64_t count;
38 Tick(): ticks(0), count(0) {}
39 void add(uint64_t a) {
40 ticks += a;
41 count++;
42 }
43 };
44 static Tick write_ticks, setattr_ticks, omap_setkeys_ticks, omap_rmkeys_ticks;
45 static Tick encode_ticks, decode_ticks, iterate_ticks;
46
47 void write(coll_t cid, const ghobject_t& oid, uint64_t off, uint64_t len,
48 const bufferlist& data) {
49 uint64_t start_time = Cycles::rdtsc();
50 t.write(cid, oid, off, len, data);
51 write_ticks.add(Cycles::rdtsc() - start_time);
52 }
53 void setattr(coll_t cid, const ghobject_t& oid, const string &name,
54 bufferlist& val) {
55 uint64_t start_time = Cycles::rdtsc();
56 t.setattr(cid, oid, name, val);
57 setattr_ticks.add(Cycles::rdtsc() - start_time);
58 }
59 void omap_setkeys(coll_t cid, const ghobject_t &oid,
60 const map<string, bufferlist> &attrset) {
61
62 uint64_t start_time = Cycles::rdtsc();
63 t.omap_setkeys(cid, oid, attrset);
64 omap_setkeys_ticks.add(Cycles::rdtsc() - start_time);
65 }
66 void omap_rmkeys(coll_t cid, const ghobject_t &oid,
67 const set<string> &keys) {
68 uint64_t start_time = Cycles::rdtsc();
69 t.omap_rmkeys(cid, oid, keys);
70 omap_rmkeys_ticks.add(Cycles::rdtsc() - start_time);
71 }
72
73 void apply_encode_decode() {
74 bufferlist bl;
75 ObjectStore::Transaction d;
76 uint64_t start_time = Cycles::rdtsc();
77 t.encode(bl);
78 encode_ticks.add(Cycles::rdtsc() - start_time);
79
80 bufferlist::iterator bliter = bl.begin();
81 start_time = Cycles::rdtsc();
82 d.decode(bliter);
83 decode_ticks.add(Cycles::rdtsc() - start_time);
84 }
85
86 void apply_iterate() {
87 uint64_t start_time = Cycles::rdtsc();
88 ObjectStore::Transaction::iterator i = t.begin();
89 while (i.have_op()) {
90 ObjectStore::Transaction::Op *op = i.decode_op();
91
92 switch (op->op) {
93 case ObjectStore::Transaction::OP_WRITE:
94 {
95 ghobject_t oid = i.get_oid(op->oid);
96 bufferlist bl;
97 i.decode_bl(bl);
98 }
99 break;
100 case ObjectStore::Transaction::OP_SETATTR:
101 {
102 ghobject_t oid = i.get_oid(op->oid);
103 string name = i.decode_string();
104 bufferlist bl;
105 i.decode_bl(bl);
106 map<string, bufferptr> to_set;
107 to_set[name] = bufferptr(bl.c_str(), bl.length());
108 }
109 break;
110 case ObjectStore::Transaction::OP_OMAP_SETKEYS:
111 {
112 ghobject_t oid = i.get_oid(op->oid);
113 map<string, bufferptr> aset;
114 i.decode_attrset(aset);
115 }
116 break;
117 case ObjectStore::Transaction::OP_OMAP_RMKEYS:
118 {
119 ghobject_t oid = i.get_oid(op->oid);
120 set<string> keys;
121 i.decode_keyset(keys);
122 }
123 break;
124 }
125 }
126 iterate_ticks.add(Cycles::rdtsc() - start_time);
127 }
128
129 static void dump_stat() {
130 cerr << " write op: " << Cycles::to_microseconds(write_ticks.ticks) << "us count: " << write_ticks.count << std::endl;
131 cerr << " setattr op: " << Cycles::to_microseconds(setattr_ticks.ticks) << "us count: " << setattr_ticks.count << std::endl;
132 cerr << " omap_setkeys op: " << Cycles::to_microseconds(Transaction::omap_setkeys_ticks.ticks) << "us count: " << Transaction::omap_setkeys_ticks.count << std::endl;
133 cerr << " omap_rmkeys op: " << Cycles::to_microseconds(Transaction::omap_rmkeys_ticks.ticks) << "us count: " << Transaction::omap_rmkeys_ticks.count << std::endl;
134 cerr << " encode op: " << Cycles::to_microseconds(Transaction::encode_ticks.ticks) << "us count: " << Transaction::encode_ticks.count << std::endl;
135 cerr << " decode op: " << Cycles::to_microseconds(Transaction::decode_ticks.ticks) << "us count: " << Transaction::decode_ticks.count << std::endl;
136 cerr << " iterate op: " << Cycles::to_microseconds(Transaction::iterate_ticks.ticks) << "us count: " << Transaction::iterate_ticks.count << std::endl;
137 }
138 };
139
140 class PerfCase {
141 static const uint64_t Kib = 1024;
142 static const uint64_t Mib = 1024 * 1024;
143 static const string info_epoch_attr;
144 static const string info_info_attr;
145 static const string attr;
146 static const string snapset_attr;
147 static const string pglog_attr;
148 static const coll_t meta_cid;
149 static const coll_t cid;
150 static const ghobject_t pglog_oid;
151 static const ghobject_t info_oid;
152 map<string, bufferlist> data;
153
154 ghobject_t create_object() {
155 bufferlist bl = generate_random(100, 1);
156 return ghobject_t(hobject_t(string("obj_")+string(bl.c_str()), string(), rand() & 2 ? CEPH_NOSNAP : rand(), rand() & 0xFF, 0, ""));
157 }
158
159
160 bufferlist generate_random(uint64_t len, int frag) {
161 static const char alphanum[] = "0123456789"
162 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
163 "abcdefghijklmnopqrstuvwxyz";
164 uint64_t per_frag = len / frag;
165 bufferlist bl;
166 for (int i = 0; i < frag; i++ ) {
167 bufferptr bp(per_frag);
168 for (unsigned int j = 0; j < len; j++) {
169 bp[j] = alphanum[rand() % (sizeof(alphanum) - 1)];
170 }
171 bl.append(bp);
172 }
173 return bl;
174 }
175 public:
176 PerfCase() {
177 uint64_t four_kb = Kib * 4;
178 uint64_t one_mb = Mib * 1;
179 uint64_t four_mb = Mib * 4;
180 data["4k"] = generate_random(four_kb, 1);
181 data["1m"] = generate_random(one_mb, 1);
182 data["4m"] = generate_random(four_mb, 1);
183 data[attr] = generate_random(256, 1);
184 data[snapset_attr] = generate_random(32, 1);
185 data[pglog_attr] = generate_random(128, 1);
186 data[info_epoch_attr] = generate_random(4, 1);
187 data[info_info_attr] = generate_random(560, 1);
188 }
189
190 uint64_t rados_write_4k(int times) {
191 uint64_t ticks = 0;
192 uint64_t len = Kib *4;
193 for (int i = 0; i < times; i++) {
194 uint64_t start_time = 0;
195 {
196 Transaction t;
197 ghobject_t oid = create_object();
198 start_time = Cycles::rdtsc();
199 t.write(cid, oid, 0, len, data["4k"]);
200 t.setattr(cid, oid, attr, data[attr]);
201 t.setattr(cid, oid, snapset_attr, data[snapset_attr]);
202 t.apply_encode_decode();
203 t.apply_iterate();
204 ticks += Cycles::rdtsc() - start_time;
205 }
206 {
207 Transaction t;
208 map<string, bufferlist> pglog_attrset;
209 map<string, bufferlist> info_attrset;
210 set<string> keys;
211 keys.insert(pglog_attr);
212 pglog_attrset[pglog_attr] = data[pglog_attr];
213 info_attrset[info_epoch_attr] = data[info_epoch_attr];
214 info_attrset[info_info_attr] = data[info_info_attr];
215 start_time = Cycles::rdtsc();
216 t.omap_setkeys(meta_cid, pglog_oid, pglog_attrset);
217 t.omap_setkeys(meta_cid, info_oid, info_attrset);
218 t.omap_rmkeys(meta_cid, pglog_oid, keys);
219 t.apply_encode_decode();
220 t.apply_iterate();
221 ticks += Cycles::rdtsc() - start_time;
222 }
223 }
224 return ticks;
225 }
226 };
227 const string PerfCase::info_epoch_attr("11.40_epoch");
228 const string PerfCase::info_info_attr("11.40_info");
229 const string PerfCase::attr("_");
230 const string PerfCase::snapset_attr("snapset");
231 const string PerfCase::pglog_attr("pglog_attr");
232 const coll_t PerfCase::meta_cid;
233 const coll_t PerfCase::cid;
234 const ghobject_t PerfCase::pglog_oid(hobject_t(sobject_t(object_t("cid_pglog"), 0)));
235 const ghobject_t PerfCase::info_oid(hobject_t(sobject_t(object_t("infos"), 0)));
236 Transaction::Tick Transaction::write_ticks, Transaction::setattr_ticks, Transaction::omap_setkeys_ticks, Transaction::omap_rmkeys_ticks;
237 Transaction::Tick Transaction::encode_ticks, Transaction::decode_ticks, Transaction::iterate_ticks;
238
239 void usage(const string &name) {
240 cerr << "Usage: " << name << " [times] "
241 << std::endl;
242 }
243
244 int main(int argc, char **argv)
245 {
246 vector<const char*> args;
247 argv_to_vec(argc, (const char **)argv, args);
248
249 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
250 CODE_ENVIRONMENT_UTILITY, 0);
251 common_init_finish(g_ceph_context);
252 g_ceph_context->_conf->apply_changes(NULL);
253 Cycles::init();
254
255 cerr << "args: " << args << std::endl;
256 if (args.size() < 1) {
257 usage(argv[0]);
258 return 1;
259 }
260
261 uint64_t times = atoi(args[0]);
262 PerfCase c;
263 uint64_t ticks = c.rados_write_4k(times);
264 Transaction::dump_stat();
265 cerr << " Total rados op " << times << " run time " << Cycles::to_microseconds(ticks) << "us." << std::endl;
266
267 return 0;
268 }