/Users/deen/code/yugabyte-db/src/yb/tserver/tablet_server-stress-test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | |
33 | | #include "yb/gutil/strings/substitute.h" |
34 | | |
35 | | #include "yb/tserver/tablet_server-test-base.h" |
36 | | |
37 | | #include "yb/util/countdown_latch.h" |
38 | | #include "yb/util/metrics.h" |
39 | | #include "yb/util/status_log.h" |
40 | | #include "yb/util/stopwatch.h" |
41 | | #include "yb/util/thread.h" |
42 | | |
43 | | DEFINE_int32(num_inserter_threads, 8, "Number of inserter threads to run"); |
44 | | DEFINE_int32(num_inserts_per_thread, 0, "Number of inserts from each thread"); |
45 | | DECLARE_bool(enable_maintenance_manager); |
46 | | |
47 | | METRIC_DEFINE_coarse_histogram(test, insert_latency, |
48 | | "Insert Latency", |
49 | | yb::MetricUnit::kMicroseconds, |
50 | | "TabletServer single threaded insert latency."); |
51 | | |
52 | | namespace yb { |
53 | | namespace tserver { |
54 | | |
55 | | class TSStressTest : public TabletServerTestBase { |
56 | | public: |
57 | | TSStressTest() |
58 | 1 | : start_latch_(FLAGS_num_inserter_threads) { |
59 | | |
60 | 1 | if (FLAGS_num_inserts_per_thread == 0) { |
61 | 1 | FLAGS_num_inserts_per_thread = AllowSlowTests() ? 100000 : 1000; |
62 | 1 | } |
63 | | |
64 | | // Re-enable the maintenance manager which is disabled by default |
65 | | // in TS tests. We want to stress the whole system including |
66 | | // flushes, etc. |
67 | 1 | FLAGS_enable_maintenance_manager = true; |
68 | 1 | } |
69 | | |
70 | 1 | void SetUp() override { |
71 | 1 | TabletServerTestBase::SetUp(); |
72 | 1 | StartTabletServer(); |
73 | | |
74 | 1 | histogram_ = METRIC_insert_latency.Instantiate(ts_test_metric_entity_); |
75 | 1 | } |
76 | | |
77 | 1 | void StartThreads() { |
78 | 9 | for (int i = 0; i < FLAGS_num_inserter_threads; i++) { |
79 | 8 | scoped_refptr<yb::Thread> new_thread; |
80 | 8 | CHECK_OK(yb::Thread::Create("test", strings::Substitute("test$0", i), |
81 | 8 | &TSStressTest::InserterThread, this, i, &new_thread)); |
82 | 8 | threads_.push_back(new_thread); |
83 | 8 | } |
84 | 1 | } |
85 | | |
86 | 1 | void JoinThreads() { |
87 | 8 | for (scoped_refptr<yb::Thread> thr : threads_) { |
88 | 8 | CHECK_OK(ThreadJoiner(thr.get()).Join()); |
89 | 8 | } |
90 | 1 | } |
91 | | |
92 | | void InserterThread(int thread_idx); |
93 | | |
94 | | protected: |
95 | | scoped_refptr<Histogram> histogram_; |
96 | | CountDownLatch start_latch_; |
97 | | std::vector<scoped_refptr<yb::Thread> > threads_; |
98 | | }; |
99 | | |
100 | 8 | void TSStressTest::InserterThread(int thread_idx) { |
101 | | // Wait for all the threads to be ready before we start. |
102 | 8 | start_latch_.CountDown(); |
103 | 8 | start_latch_.Wait(); |
104 | 8 | LOG(INFO) << "Starting inserter thread " << thread_idx << " complete"; |
105 | | |
106 | 8 | uint32_t max_rows = FLAGS_num_inserts_per_thread; |
107 | 8 | auto start_row = thread_idx * max_rows; |
108 | 8.00k | for (auto i = start_row; i < start_row + max_rows ; i++) { |
109 | 7.99k | MonoTime before = MonoTime::Now(); |
110 | 7.99k | InsertTestRowsRemote(thread_idx, i, 1); |
111 | 7.99k | MonoTime after = MonoTime::Now(); |
112 | 7.99k | MonoDelta delta = after.GetDeltaSince(before); |
113 | 7.99k | histogram_->Increment(delta.ToMicroseconds()); |
114 | 7.99k | } |
115 | 8 | LOG(INFO) << "Inserter thread " << thread_idx << " complete"; |
116 | 8 | } |
117 | | |
118 | 1 | TEST_F(TSStressTest, TestMTInserts) { |
119 | 1 | StartThreads(); |
120 | 1 | Stopwatch s(Stopwatch::ALL_THREADS); |
121 | 1 | s.start(); |
122 | 1 | JoinThreads(); |
123 | 1 | s.stop(); |
124 | 1 | int num_rows = (FLAGS_num_inserter_threads * FLAGS_num_inserts_per_thread); |
125 | 1 | LOG(INFO) << "Inserted " << num_rows << " rows in " << s.elapsed().wall_millis() << " ms"; |
126 | 1 | LOG(INFO) << "Throughput: " << (num_rows * 1000 / s.elapsed().wall_millis()) << " rows/sec"; |
127 | 1 | LOG(INFO) << "CPU efficiency: " << (num_rows / s.elapsed().user_cpu_seconds()) << " rows/cpusec"; |
128 | | |
129 | | |
130 | | // Generate the JSON. |
131 | 1 | std::stringstream out; |
132 | 1 | JsonWriter writer(&out, JsonWriter::PRETTY); |
133 | 1 | ASSERT_OK(histogram_->WriteAsJson(&writer, MetricJsonOptions())); |
134 | | |
135 | 1 | LOG(INFO) << out.str(); |
136 | 1 | } |
137 | | |
138 | | } // namespace tserver |
139 | | } // namespace yb |