]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/bench/small_io_bench.cc
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / test / bench / small_io_bench.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2
3#include <boost/scoped_ptr.hpp>
4#include <boost/lexical_cast.hpp>
5#include <boost/program_options/option.hpp>
6#include <boost/program_options/options_description.hpp>
7#include <boost/program_options/variables_map.hpp>
8#include <boost/program_options/cmdline.hpp>
9#include <boost/program_options/parsers.hpp>
10#include <iostream>
11#include <set>
12#include <sstream>
13#include <stdlib.h>
14#include <fstream>
15
16#include "common/Formatter.h"
17
18#include "bencher.h"
19#include "rados_backend.h"
20#include "detailed_stat_collector.h"
21#include "distribution.h"
22
23namespace po = boost::program_options;
24using namespace std;
25
26int main(int argc, char **argv)
27{
28 po::options_description desc("Allowed options");
29 desc.add_options()
30 ("help", "produce help message")
31 ("num-concurrent-ops", po::value<unsigned>()->default_value(10),
32 "set number of concurrent ops")
33 ("num-objects", po::value<unsigned>()->default_value(500),
34 "set number of objects to use")
35 ("object-size", po::value<unsigned>()->default_value(4<<20),
36 "set object size")
37 ("io-size", po::value<unsigned>()->default_value(4<<10),
38 "set io size")
39 ("write-ratio", po::value<double>()->default_value(0.75),
40 "set ratio of read to write")
41 ("duration", po::value<unsigned>()->default_value(0),
42 "set max duration, 0 for unlimited")
43 ("max-ops", po::value<unsigned>()->default_value(0),
44 "set max ops, 0 for unlimited")
45 ("seed", po::value<unsigned>(),
46 "seed")
47 ("ceph-client-id", po::value<string>()->default_value("admin"),
48 "set ceph client id")
49 ("pool-name", po::value<string>()->default_value("data"),
50 "set pool")
51 ("op-dump-file", po::value<string>()->default_value(""),
52 "set file for dumping op details, omit for stderr")
53 ("init-only", po::value<bool>()->default_value(false),
54 "populate object set")
55 ("do-not-init", po::value<bool>()->default_value(false),
56 "use existing object set")
57 ("use-prefix", po::value<string>()->default_value(""),
58 "use previously populated prefix")
59 ("offset-align", po::value<unsigned>()->default_value(4096),
60 "align offset by")
61 ("sequential", po::value<bool>()->default_value(false),
62 "use sequential access pattern")
63 ("disable-detailed-ops", po::value<bool>()->default_value(false),
64 "don't dump per op stats")
65 ;
66
67 po::variables_map vm;
68 po::store(po::parse_command_line(argc, argv, desc), vm);
69 po::notify(vm);
70
71 if (vm.count("help")) {
72 cout << desc << std::endl;
73 return 1;
74 }
75
76 if (vm["do-not-init"].as<bool>() && !vm["use-prefix"].as<string>().size()) {
77 cout << "Must supply prefix if do-not-init is specified" << std::endl;
78 cout << desc << std::endl;
79 return 1;
80 }
81
82 if (vm["init-only"].as<bool>() && !vm["use-prefix"].as<string>().size()) {
83 cout << "Must supply prefix for init-only" << std::endl;
84 cout << desc << std::endl;
85 return 1;
86 }
87
88 string prefix;
89 if (vm["use-prefix"].as<string>().size()) {
90 prefix = vm["use-prefix"].as<string>();
91 } else {
92 char hostname_cstr[100];
93 gethostname(hostname_cstr, 100);
94 stringstream hostpid;
95 hostpid << hostname_cstr << getpid() << "-";
96 prefix = hostpid.str();
97 }
98
99 set<string> objects;
100 for (unsigned i = 0; i < vm["num-objects"].as<unsigned>();
101 ++i) {
102 stringstream name;
103 name << prefix << "-object_" << i;
104 objects.insert(name.str());
105 }
106
107 rngen_t rng;
108 if (vm.count("seed"))
109 rng = rngen_t(vm["seed"].as<unsigned>());
110
111 set<pair<double, Bencher::OpType> > ops;
112 ops.insert(make_pair(vm["write-ratio"].as<double>(), Bencher::WRITE));
113 ops.insert(make_pair(1-vm["write-ratio"].as<double>(), Bencher::READ));
114
115 librados::Rados rados;
116 librados::IoCtx ioctx;
117 int r = rados.init(vm["ceph-client-id"].as<string>().c_str());
118 if (r < 0) {
119 cerr << "error in init r=" << r << std::endl;
120 return -r;
121 }
122 r = rados.conf_read_file(NULL);
123 if (r < 0) {
124 cerr << "error in conf_read_file r=" << r << std::endl;
125 return -r;
126 }
127 r = rados.conf_parse_env(NULL);
128 if (r < 0) {
129 cerr << "error in conf_parse_env r=" << r << std::endl;
130 return -r;
131 }
132 r = rados.connect();
133 if (r < 0) {
134 cerr << "error in connect r=" << r << std::endl;
135 return -r;
136 }
137 r = rados.ioctx_create(vm["pool-name"].as<string>().c_str(), ioctx);
138 if (r < 0) {
139 cerr << "error in ioctx_create r=" << r << std::endl;
140 return -r;
141 }
142
143 ostream *detailed_ops = 0;
144 ofstream myfile;
145 if (vm["disable-detailed-ops"].as<bool>()) {
146 detailed_ops = 0;
147 } else if (vm["op-dump-file"].as<string>().size()) {
148 myfile.open(vm["op-dump-file"].as<string>().c_str());
149 detailed_ops = &myfile;
150 } else {
151 detailed_ops = &cerr;
152 }
153
154 Distribution<
155 boost::tuple<string, uint64_t, uint64_t, Bencher::OpType> > *gen = 0;
156 if (vm["sequential"].as<bool>()) {
157 std::cout << "Using Sequential generator" << std::endl;
158 gen = new SequentialLoad(
159 objects,
160 vm["object-size"].as<unsigned>(),
161 vm["io-size"].as<unsigned>(),
162 new WeightedDist<Bencher::OpType>(rng, ops)
163 );
164 } else {
165 std::cout << "Using random generator" << std::endl;
166 gen = new FourTupleDist<string, uint64_t, uint64_t, Bencher::OpType>(
167 new RandomDist<string>(rng, objects),
168 new Align(
169 new UniformRandom(
170 rng,
171 0,
172 vm["object-size"].as<unsigned>() - vm["io-size"].as<unsigned>()),
173 vm["offset-align"].as<unsigned>()
174 ),
175 new Uniform(vm["io-size"].as<unsigned>()),
176 new WeightedDist<Bencher::OpType>(rng, ops)
177 );
178 }
179
180 Bencher bencher(
181 gen,
182 new DetailedStatCollector(1, new JSONFormatter, detailed_ops, &cout),
183 new RadosBackend(&ioctx),
184 vm["num-concurrent-ops"].as<unsigned>(),
185 vm["duration"].as<unsigned>(),
186 vm["max-ops"].as<unsigned>());
187
188 if (!vm["do-not-init"].as<bool>()) {
189 bencher.init(objects, vm["object-size"].as<unsigned>(), &std::cout);
190 cout << "Created objects..." << std::endl;
191 } else {
192 cout << "Not initing objects..." << std::endl;
193 }
194
195 if (!vm["init-only"].as<bool>()) {
196 bencher.run_bench();
197 } else {
198 cout << "init-only" << std::endl;
199 }
200
201 rados.shutdown();
202 if (vm["op-dump-file"].as<string>().size()) {
203 myfile.close();
204 }
205 return 0;
206}