]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | }; | |
9f95a23c | 44 | static Tick write_ticks, setattr_ticks, omap_setkeys_ticks, omap_rmkey_ticks; |
7c673cae FG |
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 | } | |
9f95a23c TL |
66 | void omap_rmkey(coll_t cid, const ghobject_t &oid, |
67 | const string &key) { | |
7c673cae | 68 | uint64_t start_time = Cycles::rdtsc(); |
9f95a23c TL |
69 | t.omap_rmkey(cid, oid, key); |
70 | omap_rmkey_ticks.add(Cycles::rdtsc() - start_time); | |
7c673cae FG |
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 | ||
11fdf7f2 | 80 | auto bliter = bl.cbegin(); |
7c673cae FG |
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; | |
9f95a23c | 133 | cerr << " omap_rmkey op: " << Cycles::to_microseconds(Transaction::omap_rmkey_ticks.ticks) << "us count: " << Transaction::omap_rmkey_ticks.count << std::endl; |
7c673cae FG |
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; | |
7c673cae FG |
210 | pglog_attrset[pglog_attr] = data[pglog_attr]; |
211 | info_attrset[info_epoch_attr] = data[info_epoch_attr]; | |
212 | info_attrset[info_info_attr] = data[info_info_attr]; | |
213 | start_time = Cycles::rdtsc(); | |
214 | t.omap_setkeys(meta_cid, pglog_oid, pglog_attrset); | |
215 | t.omap_setkeys(meta_cid, info_oid, info_attrset); | |
9f95a23c | 216 | t.omap_rmkey(meta_cid, pglog_oid, pglog_attr); |
7c673cae FG |
217 | t.apply_encode_decode(); |
218 | t.apply_iterate(); | |
219 | ticks += Cycles::rdtsc() - start_time; | |
220 | } | |
221 | } | |
222 | return ticks; | |
223 | } | |
224 | }; | |
225 | const string PerfCase::info_epoch_attr("11.40_epoch"); | |
226 | const string PerfCase::info_info_attr("11.40_info"); | |
227 | const string PerfCase::attr("_"); | |
228 | const string PerfCase::snapset_attr("snapset"); | |
229 | const string PerfCase::pglog_attr("pglog_attr"); | |
230 | const coll_t PerfCase::meta_cid; | |
231 | const coll_t PerfCase::cid; | |
232 | const ghobject_t PerfCase::pglog_oid(hobject_t(sobject_t(object_t("cid_pglog"), 0))); | |
233 | const ghobject_t PerfCase::info_oid(hobject_t(sobject_t(object_t("infos"), 0))); | |
9f95a23c | 234 | Transaction::Tick Transaction::write_ticks, Transaction::setattr_ticks, Transaction::omap_setkeys_ticks, Transaction::omap_rmkey_ticks; |
7c673cae FG |
235 | Transaction::Tick Transaction::encode_ticks, Transaction::decode_ticks, Transaction::iterate_ticks; |
236 | ||
237 | void usage(const string &name) { | |
238 | cerr << "Usage: " << name << " [times] " | |
239 | << std::endl; | |
240 | } | |
241 | ||
242 | int main(int argc, char **argv) | |
243 | { | |
20effc67 | 244 | auto args = argv_to_vec(argc, argv); |
7c673cae FG |
245 | |
246 | auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, | |
11fdf7f2 TL |
247 | CODE_ENVIRONMENT_UTILITY, |
248 | CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); | |
7c673cae | 249 | common_init_finish(g_ceph_context); |
11fdf7f2 | 250 | g_ceph_context->_conf.apply_changes(nullptr); |
7c673cae FG |
251 | Cycles::init(); |
252 | ||
253 | cerr << "args: " << args << std::endl; | |
254 | if (args.size() < 1) { | |
255 | usage(argv[0]); | |
256 | return 1; | |
257 | } | |
258 | ||
259 | uint64_t times = atoi(args[0]); | |
260 | PerfCase c; | |
261 | uint64_t ticks = c.rados_write_4k(times); | |
262 | Transaction::dump_stat(); | |
263 | cerr << " Total rados op " << times << " run time " << Cycles::to_microseconds(ticks) << "us." << std::endl; | |
264 | ||
265 | return 0; | |
266 | } |