]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/xattr_bench.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / xattr_bench.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) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include <stdio.h>
16 #include <time.h>
17 #include <string.h>
18 #include <iostream>
19 #include <iterator>
20 #include <sstream>
21 #include "os/bluestore/BlueStore.h"
22 #include "include/Context.h"
23 #include "common/ceph_argparse.h"
24 #include "common/ceph_mutex.h"
25 #include "common/Cond.h"
26 #include "global/global_init.h"
27 #include <boost/scoped_ptr.hpp>
28 #include <boost/random/mersenne_twister.hpp>
29 #include <boost/random/uniform_int.hpp>
30 #include <boost/random/binomial_distribution.hpp>
31 #include <gtest/gtest.h>
32
33 #include "include/unordered_map.h"
34
35 void usage(const string &name) {
36 std::cerr << "Usage: " << name << " [xattr|omap] store_path"
37 << std::endl;
38 }
39
40 const int THREADS = 5;
41
42 template <typename T>
43 typename T::iterator rand_choose(T &cont) {
44 if (std::empty(cont) == 0) {
45 return std::end(cont);
46 }
47 return std::next(std::begin(cont), rand() % cont.size());
48 }
49
50 class OnApplied : public Context {
51 public:
52 ceph::mutex *lock;
53 ceph::condition_variable *cond;
54 int *in_progress;
55 ObjectStore::Transaction *t;
56 OnApplied(ceph::mutex *lock,
57 ceph::condition_variable *cond,
58 int *in_progress,
59 ObjectStore::Transaction *t)
60 : lock(lock), cond(cond),
61 in_progress(in_progress), t(t) {
62 std::lock_guard l{*lock};
63 (*in_progress)++;
64 }
65
66 void finish(int r) override {
67 std::lock_guard l{*lock};
68 (*in_progress)--;
69 cond->notify_all();
70 }
71 };
72
73 uint64_t get_time() {
74 time_t start;
75 time(&start);
76 return start * 1000;
77 }
78
79 double print_time(uint64_t ms) {
80 return ((double)ms)/1000;
81 }
82
83 uint64_t do_run(ObjectStore *store, int attrsize, int numattrs,
84 int run,
85 int transsize, int ops,
86 ostream &out) {
87 ceph::mutex lock = ceph::make_mutex("lock");
88 ceph::condition_variable cond;
89 int in_flight = 0;
90 ObjectStore::Sequencer osr(__func__);
91 ObjectStore::Transaction t;
92 map<coll_t, pair<set<string>, ObjectStore::Sequencer*> > collections;
93 for (int i = 0; i < 3*THREADS; ++i) {
94 coll_t coll(spg_t(pg_t(0, i + 1000*run), shard_id_t::NO_SHARD));
95 t.create_collection(coll, 0);
96 set<string> objects;
97 for (int i = 0; i < transsize; ++i) {
98 stringstream obj_str;
99 obj_str << i;
100 t.touch(coll,
101 ghobject_t(hobject_t(sobject_t(obj_str.str(), CEPH_NOSNAP))));
102 objects.insert(obj_str.str());
103 }
104 collections[coll] = make_pair(objects, new ObjectStore::Sequencer(coll.to_str()));
105 }
106 store->queue_transaction(&osr, std::move(t));
107
108 bufferlist bl;
109 for (int i = 0; i < attrsize; ++i) {
110 bl.append('\0');
111 }
112
113 uint64_t start = get_time();
114 for (int i = 0; i < ops; ++i) {
115 {
116 std::unique_lock l{lock};
117 cond.wait(l, [&] { in_flight < THREADS; });
118 }
119 ObjectStore::Transaction *t = new ObjectStore::Transaction;
120 map<coll_t, pair<set<string>, ObjectStore::Sequencer*> >::iterator iter =
121 rand_choose(collections);
122 for (set<string>::iterator obj = iter->second.first.begin();
123 obj != iter->second.first.end();
124 ++obj) {
125 for (int j = 0; j < numattrs; ++j) {
126 stringstream ss;
127 ss << i << ", " << j << ", " << *obj;
128 t->setattr(iter->first,
129 ghobject_t(hobject_t(sobject_t(*obj, CEPH_NOSNAP))),
130 ss.str().c_str(),
131 bl);
132 }
133 }
134 store->queue_transaction(iter->second.second, std::move(*t),
135 new OnApplied(&lock, &cond, &in_flight,
136 t));
137 delete t;
138 }
139 {
140 std::unique_lock l{lock};
141 cond.wait(l, [&] { return in_flight == 0; });
142 }
143 return get_time() - start;
144 }
145
146 int main(int argc, char **argv) {
147 auto args = argv_to_vec(argc, argv);
148 if (args.empty()) {
149 cerr << argv[0] << ": -h or --help for usage" << std::endl;
150 exit(1);
151 }
152 if (ceph_argparse_need_usage(args)) {
153 usage(argv[0]);
154 exit(0);
155 }
156
157 auto cct = global_init(0, args, CEPH_ENTITY_TYPE_CLIENT,
158 CODE_ENVIRONMENT_UTILITY,
159 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
160 common_init_finish(g_ceph_context);
161
162 std::cerr << "args: " << args << std::endl;
163 if (args.size() < 2) {
164 usage(argv[0]);
165 return 1;
166 }
167
168 string store_path(args[1]);
169
170 boost::scoped_ptr<ObjectStore> store(new BlueStore(cct.get(), store_path));
171
172 std::cerr << "mkfs starting" << std::endl;
173 ceph_assert(!store->mkfs());
174 ceph_assert(!store->mount());
175 std::cerr << "mounted" << std::endl;
176
177 std::cerr << "attrsize\tnumattrs\ttranssize\tops\ttime" << std::endl;
178 int runs = 0;
179 int total_size = 11;
180 for (int i = 6; i < total_size; ++i) {
181 for (int j = (total_size - i); j >= 0; --j) {
182 std::cerr << "starting run " << runs << std::endl;
183 ++runs;
184 uint64_t time = do_run(store.get(), (1 << i), (1 << j), runs,
185 10,
186 1000, std::cout);
187 std::cout << (1 << i) << "\t"
188 << (1 << j) << "\t"
189 << 10 << "\t"
190 << 1000 << "\t"
191 << print_time(time) << std::endl;
192 }
193 }
194 store->umount();
195 return 0;
196 }