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