@@ -484,6 +484,55 @@ const char* EncodingName(unsigned obj_type, unsigned encoding) {
484
484
return " unknown" ;
485
485
}
486
486
487
+ struct IOStat {
488
+ uint64_t conn_received = 0 ;
489
+ uint64_t curr_conn_count = 0 ;
490
+ uint64_t cmd_total = 0 , pipelined_cmd_total = 0 ;
491
+ size_t io_read_bytes = 0 ;
492
+ uint64_t io_reads_total = 0 ;
493
+
494
+ void From (const facade::FacadeStats& fs);
495
+ void Print (RedisReplyBuilder* rb) const ;
496
+
497
+ IOStat& operator -=(const IOStat& other);
498
+ };
499
+
500
+ void IOStat::From (const facade::FacadeStats& fs) {
501
+ conn_received = fs.conn_stats .conn_received_cnt ;
502
+ curr_conn_count = fs.conn_stats .num_conns_main ;
503
+ cmd_total = fs.conn_stats .command_cnt_main ;
504
+ pipelined_cmd_total = fs.conn_stats .pipelined_cmd_cnt ;
505
+ io_read_bytes = fs.conn_stats .io_read_bytes ;
506
+ io_reads_total = fs.conn_stats .io_read_cnt ;
507
+ }
508
+
509
+ void IOStat::Print (RedisReplyBuilder* rb) const {
510
+ rb->StartCollection (6 , RedisReplyBuilder::CollectionType::MAP);
511
+ rb->SendSimpleString (" connections_received" );
512
+ rb->SendLong (conn_received);
513
+ rb->SendSimpleString (" current_conn_count" );
514
+ rb->SendLong (curr_conn_count);
515
+ rb->SendSimpleString (" commands_total" );
516
+ rb->SendLong (cmd_total);
517
+ rb->SendSimpleString (" pipelined_commands_total" );
518
+ rb->SendLong (pipelined_cmd_total);
519
+ rb->SendSimpleString (" io_read_bytes" );
520
+ rb->SendLong (io_read_bytes);
521
+ rb->SendSimpleString (" io_reads_total" );
522
+ rb->SendLong (io_reads_total);
523
+ }
524
+
525
+ IOStat& IOStat::operator -=(const IOStat& other) {
526
+ conn_received -= other.conn_received ;
527
+ curr_conn_count -= other.curr_conn_count ;
528
+ cmd_total -= other.cmd_total ;
529
+ pipelined_cmd_total -= other.pipelined_cmd_total ;
530
+ io_read_bytes -= other.io_read_bytes ;
531
+ io_reads_total -= other.io_reads_total ;
532
+
533
+ return *this ;
534
+ }
535
+
487
536
} // namespace
488
537
489
538
DebugCmd::DebugCmd (ServerFamily* owner, cluster::ClusterFamily* cf, ConnectionContext* cntx)
@@ -550,6 +599,9 @@ void DebugCmd::Run(CmdArgList args, facade::SinkReplyBuilder* builder) {
550
599
" COMPRESSION [type]"
551
600
" Estimate the compressibility of values of the given type. if no type is given, " ,
552
601
" checks compressibility of keys" ,
602
+ " IOSTATS [PS]" ,
603
+ " Prints IO stats per thread. If PS is specified, prints thread-level stats " ,
604
+ " per second." ,
553
605
" HELP" ,
554
606
" Prints this help." ,
555
607
};
@@ -625,6 +677,9 @@ void DebugCmd::Run(CmdArgList args, facade::SinkReplyBuilder* builder) {
625
677
return Compression (args.subspan (1 ), builder);
626
678
}
627
679
680
+ if (subcmd == " IOSTATS" ) {
681
+ return IOStats (args.subspan (1 ), builder);
682
+ }
628
683
string reply = UnknownSubCmd (subcmd, " DEBUG" );
629
684
return builder->SendError (reply, kSyntaxErrType );
630
685
}
@@ -1276,6 +1331,33 @@ void DebugCmd::Compression(CmdArgList args, facade::SinkReplyBuilder* builder) {
1276
1331
rb->SendDouble (ratio);
1277
1332
}
1278
1333
1334
+ void DebugCmd::IOStats (CmdArgList args, facade::SinkReplyBuilder* builder) {
1335
+ auto * rb = static_cast <RedisReplyBuilder*>(builder);
1336
+
1337
+ bool per_second = args.size () > 0 && absl::EqualsIgnoreCase (args[0 ], " PS" );
1338
+ vector<IOStat> stats (shard_set->pool ()->size ());
1339
+
1340
+ shard_set->pool ()->AwaitBrief (
1341
+ [&](unsigned index , ProactorBase*) { stats[index ].From (*facade::tl_facade_stats); });
1342
+
1343
+ if (per_second) {
1344
+ ThisFiber::SleepFor (1s);
1345
+ vector<IOStat> stats2 (shard_set->pool ()->size ());
1346
+ shard_set->pool ()->AwaitBrief (
1347
+ [&](unsigned index , ProactorBase*) { stats2[index ].From (*facade::tl_facade_stats); });
1348
+
1349
+ for (size_t i = 0 ; i < stats.size (); ++i) {
1350
+ stats2[i] -= stats[i];
1351
+ }
1352
+ stats = std::move (stats2);
1353
+ }
1354
+
1355
+ rb->StartArray (stats.size ());
1356
+ for (const auto & stat : stats) {
1357
+ stat.Print (rb);
1358
+ }
1359
+ }
1360
+
1279
1361
void DebugCmd::DoPopulateBatch (const PopulateOptions& options, const PopulateBatch& batch) {
1280
1362
boost::intrusive_ptr<Transaction> local_tx =
1281
1363
new Transaction{sf_.service ().mutable_registry ()->Find (" EXEC" )};
0 commit comments