2222#include " db_factory.h"
2323#include " measurements.h"
2424#include " utils/countdown_latch.h"
25+ #include " utils/rate_limit.h"
2526#include " utils/timer.h"
2627#include " utils/utils.h"
2728
2829void UsageMessage (const char *command);
2930bool StrStartWith (const char *str, const char *pre );
3031void ParseCommandLine (int argc, const char *argv[], ycsbc::utils::Properties &props);
3132
32- void StatusThread (ycsbc::Measurements *measurements, CountDownLatch *latch, int interval) {
3333void StatusThread (ycsbc::Measurements *measurements, ycsbc::utils::CountDownLatch *latch, int interval) {
3434 using namespace std ::chrono;
3535 time_point<system_clock> start = system_clock::now ();
@@ -51,6 +51,39 @@ void StatusThread(ycsbc::Measurements *measurements, ycsbc::utils::CountDownLatc
5151 };
5252}
5353
54+ void RateLimitThread (std::string rate_file, std::vector<ycsbc::utils::RateLimiter *> rate_limiters,
55+ ycsbc::utils::CountDownLatch *latch) {
56+ std::ifstream ifs;
57+ ifs.open (rate_file);
58+
59+ if (!ifs.is_open ()) {
60+ ycsbc::utils::Exception (" failed to open: " + rate_file);
61+ }
62+
63+ int64_t num_threads = rate_limiters.size ();
64+
65+ int64_t last_time = 0 ;
66+ while (!ifs.eof ()) {
67+ int64_t next_time;
68+ int64_t next_rate;
69+ ifs >> next_time >> next_rate;
70+
71+ if (next_time <= last_time) {
72+ ycsbc::utils::Exception (" invalid rate file" );
73+ }
74+
75+ bool done = latch->AwaitFor (next_time - last_time);
76+ if (done) {
77+ break ;
78+ }
79+ last_time = next_time;
80+
81+ for (auto x : rate_limiters) {
82+ x->SetRate (next_rate / num_threads);
83+ }
84+ }
85+ }
86+
5487int main (const int argc, const char *argv[]) {
5588 ycsbc::utils::Properties props;
5689 ParseCommandLine (argc, argv, props);
@@ -83,6 +116,7 @@ int main(const int argc, const char *argv[]) {
83116 ycsbc::CoreWorkload wl;
84117 wl.Init (props);
85118
119+ // print status periodically
86120 const bool show_status = (props.GetProperty (" status" , " false" ) == " true" );
87121 const int status_interval = std::stoi (props.GetProperty (" status.interval" , " 10" ));
88122
@@ -105,8 +139,9 @@ int main(const int argc, const char *argv[]) {
105139 if (i < total_ops % num_threads) {
106140 thread_ops++;
107141 }
142+
108143 client_threads.emplace_back (std::async (std::launch::async, ycsbc::ClientThread, dbs[i], &wl,
109- thread_ops, true , true , !do_transaction, &latch));
144+ thread_ops, true , true , !do_transaction, &latch, nullptr ));
110145 }
111146 assert ((int )client_threads.size () == num_threads);
112147
@@ -129,8 +164,14 @@ int main(const int argc, const char *argv[]) {
129164 measurements->Reset ();
130165 std::this_thread::sleep_for (std::chrono::seconds (stoi (props.GetProperty (" sleepafterload" , " 0" ))));
131166
167+
132168 // transaction phase
133169 if (do_transaction) {
170+ // initial ops per second, unlimited if <= 0
171+ const int64_t ops_limit = std::stoi (props.GetProperty (" limit.ops" , " 0" ));
172+ // rate file path for dynamic rate limiting, format "time_stamp_sec new_ops_per_second" per line
173+ std::string rate_file = props.GetProperty (" limit.file" , " " );
174+
134175 const int total_ops = stoi (props[ycsbc::CoreWorkload::OPERATION_COUNT_PROPERTY ]);
135176
136177 ycsbc::utils::CountDownLatch latch (num_threads);
@@ -143,14 +184,27 @@ int main(const int argc, const char *argv[]) {
143184 measurements, &latch, status_interval);
144185 }
145186 std::vector<std::future<int >> client_threads;
187+ std::vector<ycsbc::utils::RateLimiter *> rate_limiters;
146188 for (int i = 0 ; i < num_threads; ++i) {
147189 int thread_ops = total_ops / num_threads;
148190 if (i < total_ops % num_threads) {
149191 thread_ops++;
150192 }
193+ ycsbc::utils::RateLimiter *rlim = nullptr ;
194+ if (ops_limit > 0 || rate_file != " " ) {
195+ int64_t per_thread_ops = ops_limit / num_threads;
196+ rlim = new ycsbc::utils::RateLimiter (per_thread_ops, per_thread_ops);
197+ }
198+ rate_limiters.push_back (rlim);
151199 client_threads.emplace_back (std::async (std::launch::async, ycsbc::ClientThread, dbs[i], &wl,
152- thread_ops, false , !do_load, true , &latch));
200+ thread_ops, false , !do_load, true , &latch, rlim ));
153201 }
202+
203+ std::future<void > rlim_future;
204+ if (rate_file != " " ) {
205+ rlim_future = std::async (std::launch::async, RateLimitThread, rate_file, rate_limiters, &latch);
206+ }
207+
154208 assert ((int )client_threads.size () == num_threads);
155209
156210 int sum = 0 ;
0 commit comments