]>
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) 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" | |
23 | #include "global/global_init.h" | |
24 | #include "common/Mutex.h" | |
25 | #include "common/Cond.h" | |
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 | ||
34 | void usage(const string &name) { | |
35 | std::cerr << "Usage: " << name << " [xattr|omap] store_path store_journal" | |
36 | << std::endl; | |
37 | } | |
38 | ||
39 | const int THREADS = 5; | |
40 | ||
41 | template <typename T> | |
42 | typename 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 | ||
53 | class OnApplied : public Context { | |
54 | public: | |
55 | Mutex *lock; | |
56 | Cond *cond; | |
57 | int *in_progress; | |
58 | ObjectStore::Transaction *t; | |
59 | OnApplied(Mutex *lock, | |
60 | Cond *cond, | |
61 | int *in_progress, | |
62 | ObjectStore::Transaction *t) | |
63 | : lock(lock), cond(cond), | |
64 | in_progress(in_progress), t(t) { | |
65 | Mutex::Locker l(*lock); | |
66 | (*in_progress)++; | |
67 | } | |
68 | ||
69 | void finish(int r) override { | |
70 | Mutex::Locker l(*lock); | |
71 | (*in_progress)--; | |
72 | cond->Signal(); | |
73 | } | |
74 | }; | |
75 | ||
76 | uint64_t get_time() { | |
77 | time_t start; | |
78 | time(&start); | |
79 | return start * 1000; | |
80 | } | |
81 | ||
82 | double print_time(uint64_t ms) { | |
83 | return ((double)ms)/1000; | |
84 | } | |
85 | ||
86 | uint64_t do_run(ObjectStore *store, int attrsize, int numattrs, | |
87 | int run, | |
88 | int transsize, int ops, | |
89 | ostream &out) { | |
90 | Mutex lock("lock"); | |
91 | Cond cond; | |
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 | } | |
109 | store->apply_transaction(&osr, std::move(t)); | |
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 | { | |
119 | Mutex::Locker l(lock); | |
120 | while (in_flight >= THREADS) | |
121 | cond.Wait(lock); | |
122 | } | |
123 | ObjectStore::Transaction *t = new ObjectStore::Transaction; | |
124 | map<coll_t, pair<set<string>, ObjectStore::Sequencer*> >::iterator iter = | |
125 | rand_choose(collections); | |
126 | for (set<string>::iterator obj = iter->second.first.begin(); | |
127 | obj != iter->second.first.end(); | |
128 | ++obj) { | |
129 | for (int j = 0; j < numattrs; ++j) { | |
130 | stringstream ss; | |
131 | ss << i << ", " << j << ", " << *obj; | |
132 | t->setattr(iter->first, | |
133 | ghobject_t(hobject_t(sobject_t(*obj, CEPH_NOSNAP))), | |
134 | ss.str().c_str(), | |
135 | bl); | |
136 | } | |
137 | } | |
138 | store->queue_transaction(iter->second.second, std::move(*t), | |
139 | new OnApplied(&lock, &cond, &in_flight, | |
140 | t)); | |
141 | delete t; | |
142 | } | |
143 | { | |
144 | Mutex::Locker l(lock); | |
145 | while (in_flight) | |
146 | cond.Wait(lock); | |
147 | } | |
148 | return get_time() - start; | |
149 | } | |
150 | ||
151 | int main(int argc, char **argv) { | |
152 | vector<const char*> args; | |
153 | argv_to_vec(argc, (const char **)argv, args); | |
154 | ||
155 | auto cct = global_init(0, args, CEPH_ENTITY_TYPE_CLIENT, | |
156 | CODE_ENVIRONMENT_UTILITY, 0); | |
157 | common_init_finish(g_ceph_context); | |
158 | ||
159 | std::cerr << "args: " << args << std::endl; | |
160 | if (args.size() < 3) { | |
161 | usage(argv[0]); | |
162 | return 1; | |
163 | } | |
164 | ||
165 | string store_path(args[1]); | |
166 | string store_dev(args[2]); | |
167 | ||
168 | boost::scoped_ptr<ObjectStore> store(new FileStore(cct.get(), store_path, | |
169 | store_dev)); | |
170 | ||
171 | std::cerr << "mkfs starting" << std::endl; | |
172 | assert(!store->mkfs()); | |
173 | assert(!store->mount()); | |
174 | std::cerr << "mounted" << std::endl; | |
175 | ||
176 | std::cerr << "attrsize\tnumattrs\ttranssize\tops\ttime" << std::endl; | |
177 | int runs = 0; | |
178 | int total_size = 11; | |
179 | for (int i = 6; i < total_size; ++i) { | |
180 | for (int j = (total_size - i); j >= 0; --j) { | |
181 | std::cerr << "starting run " << runs << std::endl; | |
182 | ++runs; | |
183 | uint64_t time = do_run(store.get(), (1 << i), (1 << j), runs, | |
184 | 10, | |
185 | 1000, std::cout); | |
186 | std::cout << (1 << i) << "\t" | |
187 | << (1 << j) << "\t" | |
188 | << 10 << "\t" | |
189 | << 1000 << "\t" | |
190 | << print_time(time) << std::endl; | |
191 | } | |
192 | } | |
193 | store->umount(); | |
194 | return 0; | |
195 | } |