@@ -61,6 +61,7 @@ ABSL_FLAG(bool, noreply, false, "If true, does not wait for replies. Relevant on
61
61
ABSL_FLAG (bool , greet, true ,
62
62
" If true, sends a greeting command on each connection, "
63
63
" to make sure the connection succeeded" );
64
+ ABSL_FLAG (bool , ascii, true , " If true, use ascii characters for values" );
64
65
65
66
using namespace std ;
66
67
using namespace util ;
@@ -82,9 +83,7 @@ enum Protocol { RESP, MC_TEXT } protocol;
82
83
enum DistType { UNIFORM, NORMAL, ZIPFIAN, SEQUENTIAL } dist_type{UNIFORM};
83
84
constexpr uint16_t kNumSlots = 16384 ;
84
85
85
- string_view kTmplPatterns [] = {" __key__" sv, " __data__" sv, " __score__" sv};
86
-
87
- static string GetRandomHex (size_t len) {
86
+ static string GetRandomHex (size_t len, bool ascii) {
88
87
std::string res (len, ' \0 ' );
89
88
size_t indx = 0 ;
90
89
@@ -103,6 +102,11 @@ static string GetRandomHex(size_t len) {
103
102
}
104
103
}
105
104
105
+ if (!ascii) {
106
+ for (size_t i = 0 ; i < len; i++) {
107
+ res[i] += 80 ;
108
+ }
109
+ }
106
110
return res;
107
111
}
108
112
@@ -154,21 +158,24 @@ class CommandGenerator {
154
158
155
159
string FillSet (string_view key);
156
160
string FillGet (string_view key);
157
- void AddTemplateIndices (string_view pattern, TemplateType t);
158
161
159
162
KeyGenerator* keygen_;
160
163
uint32_t ratio_set_ = 0 , ratio_get_ = 0 ;
161
164
string command_;
162
165
163
- vector<pair<size_t , TemplateType>> key_indices_;
166
+ using CmdPart = variant<string_view, TemplateType>;
167
+ vector<CmdPart> cmd_parts_;
168
+
164
169
string value_;
165
170
bool might_hit_ = false ;
166
171
bool noreply_ = false ;
172
+ bool is_ascii_ = true ;
167
173
};
168
174
169
175
CommandGenerator::CommandGenerator (KeyGenerator* keygen) : keygen_(keygen) {
170
176
command_ = GetFlag (FLAGS_command);
171
- value_ = string (GetFlag (FLAGS_d), ' a' );
177
+ is_ascii_ = GetFlag (FLAGS_ascii);
178
+ value_ = string (GetFlag (FLAGS_d), is_ascii_ ? ' a' : char (130 ));
172
179
173
180
if (command_.empty ()) {
174
181
pair<string, string> ratio_str = absl::StrSplit (GetFlag (FLAGS_ratio), ' :' );
@@ -177,12 +184,24 @@ CommandGenerator::CommandGenerator(KeyGenerator* keygen) : keygen_(keygen) {
177
184
return ;
178
185
}
179
186
180
- AddTemplateIndices (kTmplPatterns [KEY], KEY);
181
- AddTemplateIndices (kTmplPatterns [VALUE], VALUE);
182
- AddTemplateIndices (kTmplPatterns [SCORE], SCORE);
183
- sort (key_indices_.begin (), key_indices_.end ());
184
- if (absl::StartsWithIgnoreCase (command_, " get" ) || absl::StartsWithIgnoreCase (command_, " mget" )) {
185
- might_hit_ = true ;
187
+ vector<string_view> parts = absl::StrSplit (command_, ' ' , absl::SkipEmpty ());
188
+ for (string_view p : parts) {
189
+ if (p == " __key__" sv) {
190
+ cmd_parts_.emplace_back (KEY);
191
+ } else if (p == " __data__" sv) {
192
+ cmd_parts_.emplace_back (VALUE);
193
+ } else if (p == " __score__" sv) {
194
+ cmd_parts_.emplace_back (SCORE);
195
+ } else {
196
+ cmd_parts_.emplace_back (p);
197
+ }
198
+ }
199
+
200
+ if (!cmd_parts_.empty ()) {
201
+ const string_view* cmd = get_if<string_view>(&cmd_parts_.front ());
202
+ if (cmd) {
203
+ might_hit_ = absl::EqualsIgnoreCase (*cmd, " get" ) || absl::StartsWithIgnoreCase (*cmd, " mget" );
204
+ }
186
205
}
187
206
}
188
207
@@ -204,58 +223,54 @@ string CommandGenerator::Next(SlotRange range) {
204
223
return FillGet (key);
205
224
}
206
225
207
- size_t last_pos = 0 ;
208
- const size_t kPatLen [] = {kTmplPatterns [KEY].size (), kTmplPatterns [VALUE].size (),
209
- kTmplPatterns [SCORE].size ()};
210
226
string str, gen_cmd;
211
- for (auto [pos, type] : key_indices_) {
212
- switch (type) {
213
- case KEY:
214
- str = (*keygen_)(slot_id);
215
- break ;
216
- case VALUE:
217
- str = GetRandomHex (value_.size ());
218
- break ;
219
- case SCORE: {
220
- uniform_real_distribution<double > uniform (0 , 1 );
221
- str = absl::StrCat (uniform (bit_gen));
227
+ absl::StrAppend (&gen_cmd, " *" , cmd_parts_.size (), " \r\n " );
228
+ for (const CmdPart& part : cmd_parts_) {
229
+ if (auto p = get_if<string_view>(&part)) {
230
+ absl::StrAppend (&gen_cmd, " $" , p->size (), " \r\n " , *p, " \r\n " );
231
+ } else {
232
+ switch (get<TemplateType>(part)) {
233
+ case KEY:
234
+ str = (*keygen_)(slot_id);
235
+ break ;
236
+ case VALUE:
237
+ str = GetRandomHex (value_.size (), is_ascii_);
238
+ break ;
239
+ case SCORE: {
240
+ uniform_real_distribution<double > uniform (0 , 1 );
241
+ str = absl::StrCat (uniform (bit_gen));
242
+ }
222
243
}
244
+ absl::StrAppend (&gen_cmd, " $" , str.size (), " \r\n " , str, " \r\n " );
223
245
}
224
- absl::StrAppend (&gen_cmd, command_.substr (last_pos, pos - last_pos), str);
225
- last_pos = pos + kPatLen [type];
226
246
}
227
- absl::StrAppend (&gen_cmd, command_.substr (last_pos), " \r\n " );
228
247
229
248
return gen_cmd;
230
249
}
231
250
232
251
string CommandGenerator::FillSet (string_view key) {
252
+ string res;
253
+
233
254
if (protocol == RESP) {
234
- return absl::StrCat (" set " , key, " " , value_, " \r\n " );
235
- }
255
+ absl::StrAppend (&res, " *3\r\n $3\r\n set\r\n $" , key.size (), " \r\n " , key);
256
+ absl::StrAppend (&res, " \r\n $" , value_.size (), " \r\n " , value_, " \r\n " );
257
+ } else {
258
+ DCHECK_EQ (protocol, MC_TEXT);
259
+ absl::StrAppend (&res, " set " , key, " 0 0 " , value_.size ());
260
+ if (GetFlag (FLAGS_noreply)) {
261
+ absl::StrAppend (&res, " noreply" );
262
+ noreply_ = true ;
263
+ }
236
264
237
- DCHECK_EQ (protocol, MC_TEXT);
238
- string res;
239
- absl::StrAppend (&res, " set " , key, " 0 0 " , value_.size ());
240
- if (GetFlag (FLAGS_noreply)) {
241
- absl::StrAppend (&res, " noreply" );
242
- noreply_ = true ;
265
+ absl::StrAppend (&res, " \r\n " , value_, " \r\n " );
243
266
}
244
-
245
- absl::StrAppend (&res, " \r\n " , value_, " \r\n " );
246
267
return res;
247
268
}
248
269
249
270
string CommandGenerator::FillGet (string_view key) {
250
271
return absl::StrCat (" get " , key, " \r\n " );
251
272
}
252
273
253
- void CommandGenerator::AddTemplateIndices (string_view pattern, TemplateType t) {
254
- for (size_t pos = 0 ; (pos = command_.find (pattern, pos)) != string::npos; pos += pattern.size ()) {
255
- key_indices_.emplace_back (pos, t);
256
- }
257
- }
258
-
259
274
struct ClientStats {
260
275
base::Histogram hist;
261
276
@@ -766,16 +781,16 @@ void TLocalClient::AdjustCycle() {
766
781
767
782
thread_local unique_ptr<TLocalClient> client;
768
783
769
- void WatchFiber (atomic_bool* finish_signal, ProactorPool* pp) {
784
+ void WatchFiber (size_t num_shards, atomic_bool* finish_signal, ProactorPool* pp) {
770
785
fb2::Mutex mutex;
771
786
772
787
int64_t start_time = absl::GetCurrentTimeNanos ();
773
788
LOG (INFO) << " Started watching" ;
774
789
775
790
int64_t last_print = start_time;
776
791
uint64_t num_last_resp_cnt = 0 ;
777
-
778
- uint64_t resp_goal = GetFlag (FLAGS_c) * pp->size () * GetFlag (FLAGS_n);
792
+ num_shards = max< size_t >(num_shards, 1u );
793
+ uint64_t resp_goal = GetFlag (FLAGS_c) * pp->size () * GetFlag (FLAGS_n) * num_shards ;
779
794
uint32_t time_limit = GetFlag (FLAGS_test_time);
780
795
781
796
while (*finish_signal == false ) {
@@ -1007,7 +1022,8 @@ int main(int argc, char* argv[]) {
1007
1022
client->Start (key_minimum + index * thread_key_step, key_max, interval);
1008
1023
});
1009
1024
1010
- auto watch_fb = pp->GetNextProactor ()->LaunchFiber ([&] { WatchFiber (&finish, pp.get ()); });
1025
+ auto watch_fb =
1026
+ pp->GetNextProactor ()->LaunchFiber ([&] { WatchFiber (shards.size (), &finish, pp.get ()); });
1011
1027
const absl::Time start_time = absl::Now ();
1012
1028
1013
1029
// The actual run.
0 commit comments