1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
5 #include <boost/scoped_ptr.hpp>
6 #include <boost/lexical_cast.hpp>
7 #include <boost/program_options/option.hpp>
8 #include <boost/program_options/options_description.hpp>
9 #include <boost/program_options/variables_map.hpp>
10 #include <boost/program_options/cmdline.hpp>
11 #include <boost/program_options/parsers.hpp>
18 #include "common/Formatter.h"
21 #include "rados_backend.h"
22 #include "detailed_stat_collector.h"
23 #include "distribution.h"
24 #include "global/global_init.h"
25 #include "os/ObjectStore.h"
26 #include "dumb_backend.h"
28 namespace po
= boost::program_options
;
31 int main(int argc
, char **argv
)
33 po::options_description
desc("Allowed options");
35 ("help", "produce help message")
36 ("num-concurrent-ops", po::value
<unsigned>()->default_value(10),
37 "set number of concurrent ops")
38 ("num-objects", po::value
<unsigned>()->default_value(500),
39 "set number of objects to use")
40 ("object-size", po::value
<unsigned>()->default_value(4<<20),
42 ("io-size", po::value
<unsigned>()->default_value(4<<10),
44 ("write-ratio", po::value
<double>()->default_value(0.75),
45 "set ratio of read to write")
46 ("duration", po::value
<unsigned>()->default_value(0),
47 "set max duration, 0 for unlimited")
48 ("max-ops", po::value
<unsigned>()->default_value(0),
49 "set max ops, 0 for unlimited")
50 ("seed", po::value
<unsigned>(),
52 ("num-colls", po::value
<unsigned>()->default_value(20),
53 "number of collections")
54 ("op-dump-file", po::value
<string
>()->default_value(""),
55 "set file for dumping op details, omit for stderr")
56 ("filestore-path", po::value
<string
>(),
57 "path to filestore directory, mandatory")
58 ("offset-align", po::value
<unsigned>()->default_value(4096),
60 ("fsync", po::value
<bool>()->default_value(false),
61 "fsync after each write")
62 ("sync-file-range", po::value
<bool>()->default_value(false),
63 "sync-file-range after each write")
64 ("fadvise", po::value
<bool>()->default_value(false),
65 "fadvise after each write")
66 ("sync-interval", po::value
<unsigned>()->default_value(30),
68 ("sequential", po::value
<bool>()->default_value(false),
69 "use sequential access pattern")
70 ("disable-detailed-ops", po::value
<bool>()->default_value(false),
71 "don't dump per op stats")
74 vector
<string
> ceph_option_strings
;
77 po::parsed_options parsed
=
78 po::command_line_parser(argc
, argv
).options(desc
).allow_unregistered().run();
84 ceph_option_strings
= po::collect_unrecognized(parsed
.options
,
85 po::include_positional
);
86 } catch(po::error
&e
) {
87 std::cerr
<< e
.what() << std::endl
;
90 vector
<const char *> ceph_options
, def_args
;
91 ceph_options
.reserve(ceph_option_strings
.size());
92 for (vector
<string
>::iterator i
= ceph_option_strings
.begin();
93 i
!= ceph_option_strings
.end();
95 ceph_options
.push_back(i
->c_str());
98 auto cct
= global_init(
99 &def_args
, ceph_options
, CEPH_ENTITY_TYPE_CLIENT
,
100 CODE_ENVIRONMENT_UTILITY
,
101 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
102 common_init_finish(g_ceph_context
);
103 g_ceph_context
->_conf
->apply_changes(NULL
);
105 if (!vm
.count("filestore-path")) {
106 cout
<< "Must provide filestore-path" << std::endl
107 << desc
<< std::endl
;
111 if (vm
.count("help")) {
112 cout
<< desc
<< std::endl
;
117 if (vm
.count("seed"))
118 rng
= rngen_t(vm
["seed"].as
<unsigned>());
120 set
<pair
<double, Bencher::OpType
> > ops
;
121 ops
.insert(make_pair(vm
["write-ratio"].as
<double>(), Bencher::WRITE
));
122 ops
.insert(make_pair(1-vm
["write-ratio"].as
<double>(), Bencher::READ
));
124 cout
<< "Creating objects.." << std::endl
;
126 for (uint64_t i
= 0; i
< vm
["object-size"].as
<unsigned>(); ++i
) {
131 for (uint64_t num
= 0; num
< vm
["num-objects"].as
<unsigned>(); ++num
) {
132 unsigned col_num
= num
% vm
["num-colls"].as
<unsigned>();
133 stringstream coll
, obj
;
134 coll
<< "collection_" << col_num
;
135 obj
<< "obj_" << num
;
136 if (num
== col_num
) {
137 std::cout
<< "collection " << coll
.str() << std::endl
;
139 vm
["filestore-path"].as
<string
>() + string("/") + coll
.str());
144 std::cerr
<< "Error " << errno
<< " creating collection" << std::endl
;
148 objects
.insert(coll
.str() + "/" + obj
.str());
150 string
meta_str(vm
["filestore-path"].as
<string
>() + string("/meta"));
155 std::cerr
<< "Error " << errno
<< " creating collection" << std::endl
;
158 r
= ::open(meta_str
.c_str(), 0);
160 std::cerr
<< "Error " << errno
<< " opening meta" << std::endl
;
165 ostream
*detailed_ops
= 0;
167 if (vm
["disable-detailed-ops"].as
<bool>()) {
169 } else if (vm
["op-dump-file"].as
<string
>().size()) {
170 myfile
.open(vm
["op-dump-file"].as
<string
>().c_str());
171 detailed_ops
= &myfile
;
173 detailed_ops
= &cerr
;
177 boost::tuple
<string
, uint64_t, uint64_t, Bencher::OpType
> > *gen
= 0;
178 if (vm
["sequential"].as
<bool>()) {
179 std::cout
<< "Using Sequential generator" << std::endl
;
180 gen
= new SequentialLoad(
182 vm
["object-size"].as
<unsigned>(),
183 vm
["io-size"].as
<unsigned>(),
184 new WeightedDist
<Bencher::OpType
>(rng
, ops
)
187 std::cout
<< "Using random generator" << std::endl
;
188 gen
= new FourTupleDist
<string
, uint64_t, uint64_t, Bencher::OpType
>(
189 new RandomDist
<string
>(rng
, objects
),
194 vm
["object-size"].as
<unsigned>() - vm
["io-size"].as
<unsigned>()),
195 vm
["offset-align"].as
<unsigned>()
197 new Uniform(vm
["io-size"].as
<unsigned>()),
198 new WeightedDist
<Bencher::OpType
>(rng
, ops
)
202 #ifndef HAVE_SYNC_FILE_RANGE
203 if (vm
["sync-file-range"].as
<bool>())
204 std::cerr
<< "Warning: sync_file_range(2) not supported!" << std::endl
;
207 #ifndef HAVE_POSIX_FADVISE
208 if (vm
["fadvise"].as
<bool>())
209 std::cerr
<< "Warning: posix_fadvise(2) not supported!" << std::endl
;
214 new DetailedStatCollector(1, new JSONFormatter
, detailed_ops
, &cout
),
216 vm
["filestore-path"].as
<string
>(),
217 vm
["fsync"].as
<bool>(),
218 vm
["sync-file-range"].as
<bool>(),
219 vm
["fadvise"].as
<bool>(),
220 vm
["sync-interval"].as
<unsigned>(),
224 vm
["num-concurrent-ops"].as
<unsigned>(),
225 vm
["duration"].as
<unsigned>(),
226 vm
["max-ops"].as
<unsigned>());
228 bencher
.init(objects
, vm
["object-size"].as
<unsigned>(), &std::cout
);
229 cout
<< "Created objects..." << std::endl
;
233 if (vm
["op-dump-file"].as
<string
>().size()) {