]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/perf_counters.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / perf_counters.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) 2011 New Dream Network
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 #include "include/int_types.h"
15 #include "include/types.h" // FIXME: ordering shouldn't be important, but right
16 // now, this include has to come before the others.
17
18
19 #include "common/perf_counters_collection.h"
20 #include "common/admin_socket_client.h"
21 #include "common/ceph_context.h"
22 #include "common/config.h"
23 #include "common/errno.h"
24 #include "common/safe_io.h"
25
26 #include "common/code_environment.h"
27 #include "global/global_context.h"
28 #include "global/global_init.h"
29 #include "include/msgr.h" // for CEPH_ENTITY_TYPE_CLIENT
30 #include "gtest/gtest.h"
31
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <map>
35 #include <poll.h>
36 #include <sstream>
37 #include <stdint.h>
38 #include <string.h>
39 #include <string>
40 #include <sys/socket.h>
41 #include <sys/types.h>
42 #include <sys/un.h>
43 #include <time.h>
44 #include <unistd.h>
45 #include <thread>
46
47 #include "common/common_init.h"
48
49 using namespace std;
50
51 int main(int argc, char **argv) {
52 map<string,string> defaults = {
53 { "admin_socket", get_rand_socket_path() }
54 };
55 std::vector<const char*> args;
56 auto cct = global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT,
57 CODE_ENVIRONMENT_UTILITY,
58 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE|
59 CINIT_FLAG_NO_CCT_PERF_COUNTERS);
60 common_init_finish(g_ceph_context);
61 ::testing::InitGoogleTest(&argc, argv);
62 return RUN_ALL_TESTS();
63 }
64
65 TEST(PerfCounters, SimpleTest) {
66 AdminSocketClient client(get_rand_socket_path());
67 std::string message;
68 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\" }", &message));
69 ASSERT_EQ("{}\n", message);
70 }
71
72 enum {
73 TEST_PERFCOUNTERS1_ELEMENT_FIRST = 200,
74 TEST_PERFCOUNTERS1_ELEMENT_1,
75 TEST_PERFCOUNTERS1_ELEMENT_2,
76 TEST_PERFCOUNTERS1_ELEMENT_3,
77 TEST_PERFCOUNTERS1_ELEMENT_LAST,
78 };
79
80 std::string sd(const char *c)
81 {
82 std::string ret(c);
83 std::string::size_type sz = ret.size();
84 for (std::string::size_type i = 0; i < sz; ++i) {
85 if (ret[i] == '\'') {
86 ret[i] = '\"';
87 }
88 }
89 return ret;
90 }
91
92 static PerfCounters* setup_test_perfcounters1(CephContext *cct)
93 {
94 PerfCountersBuilder bld(cct, "test_perfcounter_1",
95 TEST_PERFCOUNTERS1_ELEMENT_FIRST, TEST_PERFCOUNTERS1_ELEMENT_LAST);
96 bld.add_u64(TEST_PERFCOUNTERS1_ELEMENT_1, "element1");
97 bld.add_time(TEST_PERFCOUNTERS1_ELEMENT_2, "element2");
98 bld.add_time_avg(TEST_PERFCOUNTERS1_ELEMENT_3, "element3");
99 return bld.create_perf_counters();
100 }
101
102 TEST(PerfCounters, SinglePerfCounters) {
103 PerfCountersCollection *coll = g_ceph_context->get_perfcounters_collection();
104 PerfCounters* fake_pf = setup_test_perfcounters1(g_ceph_context);
105 coll->add(fake_pf);
106 AdminSocketClient client(get_rand_socket_path());
107 std::string msg;
108 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
109 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":0,"
110 "\"element2\":0.000000000,\"element3\":{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}}}"), msg);
111 fake_pf->inc(TEST_PERFCOUNTERS1_ELEMENT_1);
112 fake_pf->tset(TEST_PERFCOUNTERS1_ELEMENT_2, utime_t(0, 500000000));
113 fake_pf->tinc(TEST_PERFCOUNTERS1_ELEMENT_3, utime_t(100, 0));
114 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
115 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":1,"
116 "\"element2\":0.500000000,\"element3\":{\"avgcount\":1,\"sum\":100.000000000,\"avgtime\":100.000000000}}}"), msg);
117 fake_pf->tinc(TEST_PERFCOUNTERS1_ELEMENT_3, utime_t());
118 fake_pf->tinc(TEST_PERFCOUNTERS1_ELEMENT_3, utime_t(20,0));
119 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
120 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":1,\"element2\":0.500000000,"
121 "\"element3\":{\"avgcount\":3,\"sum\":120.000000000,\"avgtime\":40.000000000}}}"), msg);
122
123 fake_pf->reset();
124 msg.clear();
125 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
126 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":1,"
127 "\"element2\":0.000000000,\"element3\":{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}}}"), msg);
128
129 }
130
131 enum {
132 TEST_PERFCOUNTERS2_ELEMENT_FIRST = 400,
133 TEST_PERFCOUNTERS2_ELEMENT_FOO,
134 TEST_PERFCOUNTERS2_ELEMENT_BAR,
135 TEST_PERFCOUNTERS2_ELEMENT_LAST,
136 };
137
138 static PerfCounters* setup_test_perfcounter2(CephContext *cct)
139 {
140 PerfCountersBuilder bld(cct, "test_perfcounter_2",
141 TEST_PERFCOUNTERS2_ELEMENT_FIRST, TEST_PERFCOUNTERS2_ELEMENT_LAST);
142 bld.add_u64(TEST_PERFCOUNTERS2_ELEMENT_FOO, "foo");
143 bld.add_time(TEST_PERFCOUNTERS2_ELEMENT_BAR, "bar");
144 return bld.create_perf_counters();
145 }
146
147 TEST(PerfCounters, MultiplePerfCounters) {
148 PerfCountersCollection *coll = g_ceph_context->get_perfcounters_collection();
149 coll->clear();
150 PerfCounters* fake_pf1 = setup_test_perfcounters1(g_ceph_context);
151 PerfCounters* fake_pf2 = setup_test_perfcounter2(g_ceph_context);
152 coll->add(fake_pf1);
153 coll->add(fake_pf2);
154 AdminSocketClient client(get_rand_socket_path());
155 std::string msg;
156
157 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
158 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":0,\"element2\":0.000000000,\"element3\":"
159 "{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}},\"test_perfcounter_2\":{\"foo\":0,\"bar\":0.000000000}}"), msg);
160
161 fake_pf1->inc(TEST_PERFCOUNTERS1_ELEMENT_1);
162 fake_pf1->inc(TEST_PERFCOUNTERS1_ELEMENT_1, 5);
163 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
164 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":6,\"element2\":0.000000000,\"element3\":"
165 "{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}},\"test_perfcounter_2\":{\"foo\":0,\"bar\":0.000000000}}"), msg);
166
167 coll->reset(string("test_perfcounter_1"));
168 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
169 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":6,\"element2\":0.000000000,\"element3\":"
170 "{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}},\"test_perfcounter_2\":{\"foo\":0,\"bar\":0.000000000}}"), msg);
171
172 fake_pf1->inc(TEST_PERFCOUNTERS1_ELEMENT_1);
173 fake_pf1->inc(TEST_PERFCOUNTERS1_ELEMENT_1, 6);
174 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
175 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":13,\"element2\":0.000000000,\"element3\":"
176 "{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}},\"test_perfcounter_2\":{\"foo\":0,\"bar\":0.000000000}}"), msg);
177
178 coll->reset(string("all"));
179 msg.clear();
180 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
181 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":13,\"element2\":0.000000000,\"element3\":"
182 "{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}},\"test_perfcounter_2\":{\"foo\":0,\"bar\":0.000000000}}"), msg);
183
184 coll->remove(fake_pf2);
185 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
186 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":13,\"element2\":0.000000000,"
187 "\"element3\":{\"avgcount\":0,\"sum\":0.000000000,\"avgtime\":0.000000000}}}"), msg);
188 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf schema\", \"format\": \"json\" }", &msg));
189 ASSERT_EQ(sd("{\"test_perfcounter_1\":{\"element1\":{\"type\":2,\"metric_type\":\"gauge\",\"value_type\":\"integer\",\"description\":\"\",\"nick\":\"\",\"priority\":0,\"units\":\"none\"},\"element2\":{\"type\":1,\"metric_type\":\"gauge\",\"value_type\":\"real\",\"description\":\"\",\"nick\":\"\",\"priority\":0,\"units\":\"none\"},\"element3\":{\"type\":5,\"metric_type\":\"gauge\",\"value_type\":\"real-integer-pair\",\"description\":\"\",\"nick\":\"\",\"priority\":0,\"units\":\"none\"}}}"), msg);
190 coll->clear();
191 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf dump\", \"format\": \"json\" }", &msg));
192 ASSERT_EQ("{}", msg);
193 }
194
195 TEST(PerfCounters, ResetPerfCounters) {
196 AdminSocketClient client(get_rand_socket_path());
197 std::string msg;
198 PerfCountersCollection *coll = g_ceph_context->get_perfcounters_collection();
199 coll->clear();
200 PerfCounters* fake_pf1 = setup_test_perfcounters1(g_ceph_context);
201 coll->add(fake_pf1);
202
203 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf reset\", \"var\": \"all\", \"format\": \"json\" }", &msg));
204 ASSERT_EQ(sd("{\"success\":\"perf reset all\"}"), msg);
205
206 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf reset\", \"var\": \"test_perfcounter_1\", \"format\": \"json\" }", &msg));
207 ASSERT_EQ(sd("{\"success\":\"perf reset test_perfcounter_1\"}"), msg);
208
209 coll->clear();
210 ASSERT_EQ("", client.do_request("{ \"prefix\": \"perf reset\", \"var\": \"test_perfcounter_1\", \"format\": \"json\" }", &msg));
211 ASSERT_EQ(sd("{\"error\":\"Not find: test_perfcounter_1\"}"), msg);
212 }
213
214 enum {
215 TEST_PERFCOUNTERS3_ELEMENT_FIRST = 400,
216 TEST_PERFCOUNTERS3_ELEMENT_READ,
217 TEST_PERFCOUNTERS3_ELEMENT_LAST,
218 };
219
220 static std::shared_ptr<PerfCounters> setup_test_perfcounter3(CephContext* cct) {
221 PerfCountersBuilder bld(cct, "test_percounter_3",
222 TEST_PERFCOUNTERS3_ELEMENT_FIRST, TEST_PERFCOUNTERS3_ELEMENT_LAST);
223 bld.add_time_avg(TEST_PERFCOUNTERS3_ELEMENT_READ, "read_avg");
224 std::shared_ptr<PerfCounters> p(bld.create_perf_counters());
225 return p;
226 }
227
228 static void counters_inc_test(std::shared_ptr<PerfCounters> fake_pf) {
229 int i = 100000;
230 utime_t t;
231
232 // set to 1 nsec
233 t.set_from_double(0.000000001);
234 while (i--) {
235 // increase by one, make sure data.u64 equal to data.avgcount
236 fake_pf->tinc(TEST_PERFCOUNTERS3_ELEMENT_READ, t);
237 }
238 }
239
240 static void counters_readavg_test(std::shared_ptr<PerfCounters> fake_pf) {
241 int i = 100000;
242
243 while (i--) {
244 std::pair<uint64_t, uint64_t> dat = fake_pf->get_tavg_ns(TEST_PERFCOUNTERS3_ELEMENT_READ);
245 // sum and count should be identical as we increment TEST_PERCOUNTERS_ELEMENT_READ by 1 nsec eveytime
246 ASSERT_EQ(dat.first, dat.second);
247 }
248 }
249
250 TEST(PerfCounters, read_avg) {
251 std::shared_ptr<PerfCounters> fake_pf = setup_test_perfcounter3(g_ceph_context);
252
253 std::thread t1(counters_inc_test, fake_pf);
254 std::thread t2(counters_readavg_test, fake_pf);
255 t2.join();
256 t1.join();
257 }