@@ -555,6 +555,7 @@ type basicCopRuntimeStats struct {
555
555
procTimes Percentile [Duration ]
556
556
// executor extra infos
557
557
tiflashScanContext TiFlashScanContext
558
+ tiflashWaitSummary TiFlashWaitSummary
558
559
}
559
560
560
561
type canGetFloat64 interface {
@@ -682,7 +683,10 @@ func (p *Percentile[valueType]) Sum() float64 {
682
683
// String implements the RuntimeStats interface.
683
684
func (e * basicCopRuntimeStats ) String () string {
684
685
if e .storeType == "tiflash" {
685
- return fmt .Sprintf ("time:%v, loops:%d, threads:%d, " , FormatDuration (time .Duration (e .consume .Load ())), e .loop .Load (), e .threads ) + e .tiflashScanContext .String ()
686
+ if e .tiflashWaitSummary .CanBeIgnored () {
687
+ return fmt .Sprintf ("time:%v, loops:%d, threads:%d, %s" , FormatDuration (time .Duration (e .consume .Load ())), e .loop .Load (), e .threads , e .tiflashScanContext .String ())
688
+ }
689
+ return fmt .Sprintf ("time:%v, loops:%d, threads:%d, %s, %s" , FormatDuration (time .Duration (e .consume .Load ())), e .loop .Load (), e .threads , e .tiflashWaitSummary .String (), e .tiflashScanContext .String ())
686
690
}
687
691
return fmt .Sprintf ("time:%v, loops:%d" , FormatDuration (time .Duration (e .consume .Load ())), e .loop .Load ())
688
692
}
@@ -700,6 +704,7 @@ func (e *basicCopRuntimeStats) Clone() RuntimeStats {
700
704
stats .consume .Store (e .consume .Load ())
701
705
stats .rows .Store (e .rows .Load ())
702
706
stats .tiflashScanContext = e .tiflashScanContext .Clone ()
707
+ stats .tiflashWaitSummary = e .tiflashWaitSummary .Clone ()
703
708
return stats
704
709
}
705
710
@@ -720,6 +725,7 @@ func (e *basicCopRuntimeStats) Merge(rs RuntimeStats) {
720
725
e .procTimes .MergePercentile (& tmp .procTimes )
721
726
}
722
727
e .tiflashScanContext .Merge (tmp .tiflashScanContext )
728
+ e .tiflashWaitSummary .Merge (tmp .tiflashWaitSummary )
723
729
}
724
730
725
731
// Tp implements the RuntimeStats interface.
@@ -799,7 +805,14 @@ func (crs *CopRuntimeStats) RecordOneCopTask(address string, summary *tipb.Execu
799
805
totalVectorIdxReadVecTimeMs : summary .GetTiflashScanContext ().GetTotalVectorIdxReadVecTimeMs (),
800
806
totalVectorIdxReadOthersTimeMs : summary .GetTiflashScanContext ().GetTotalVectorIdxReadOthersTimeMs (),
801
807
},
808
+ tiflashWaitSummary : TiFlashWaitSummary {
809
+ executionTime : * summary .TimeProcessedNs ,
810
+ minTSOWaitTime : summary .GetTiflashWaitSummary ().GetMinTSOWaitNs (),
811
+ pipelineBreakerWaitTime : summary .GetTiflashWaitSummary ().GetPipelineBreakerWaitNs (),
812
+ pipelineQueueWaitTime : summary .GetTiflashWaitSummary ().GetPipelineQueueWaitNs (),
813
+ },
802
814
}
815
+
803
816
for _ , instance := range summary .GetTiflashScanContext ().GetRegionsOfInstance () {
804
817
data .tiflashScanContext .regionsOfInstance [instance .GetInstanceId ()] = instance .GetRegionNum ()
805
818
}
@@ -826,7 +839,7 @@ func (crs *CopRuntimeStats) GetTasks() (totalTasks int32) {
826
839
}
827
840
828
841
// MergeBasicStats traverses basicCopRuntimeStats in the CopRuntimeStats and collects some useful information.
829
- func (crs * CopRuntimeStats ) MergeBasicStats () (procTimes Percentile [Duration ], totalTime time.Duration , totalTasks , totalLoops , totalThreads int32 , totalTiFlashScanContext TiFlashScanContext ) {
842
+ func (crs * CopRuntimeStats ) MergeBasicStats () (procTimes Percentile [Duration ], totalTime time.Duration , totalTasks , totalLoops , totalThreads int32 , totalTiFlashScanContext TiFlashScanContext , totalTiFlashWaitSummary TiFlashWaitSummary ) {
830
843
totalTiFlashScanContext = TiFlashScanContext {
831
844
regionsOfInstance : make (map [string ]uint64 ),
832
845
}
@@ -836,6 +849,7 @@ func (crs *CopRuntimeStats) MergeBasicStats() (procTimes Percentile[Duration], t
836
849
totalLoops += instanceStats .loop .Load ()
837
850
totalThreads += instanceStats .threads
838
851
totalTiFlashScanContext .Merge (instanceStats .tiflashScanContext )
852
+ totalTiFlashWaitSummary .Merge (instanceStats .tiflashWaitSummary )
839
853
totalTasks += instanceStats .totalTasks
840
854
}
841
855
return
@@ -846,15 +860,18 @@ func (crs *CopRuntimeStats) String() string {
846
860
return ""
847
861
}
848
862
849
- procTimes , totalTime , totalTasks , totalLoops , totalThreads , totalTiFlashScanContext := crs .MergeBasicStats ()
863
+ procTimes , totalTime , totalTasks , totalLoops , totalThreads , totalTiFlashScanContext , totalTiFlashWaitSummary := crs .MergeBasicStats ()
850
864
avgTime := time .Duration (totalTime .Nanoseconds () / int64 (totalTasks ))
851
865
isTiFlashCop := crs .storeType == "tiflash"
852
866
853
867
buf := bytes .NewBuffer (make ([]byte , 0 , 16 ))
854
868
{
855
- printTiFlashScanContext := func () {
869
+ printTiFlashSpecificInfo := func () {
856
870
if isTiFlashCop {
857
871
fmt .Fprintf (buf , ", threads:%d}" , totalThreads )
872
+ if ! totalTiFlashWaitSummary .CanBeIgnored () {
873
+ buf .WriteString (", " + totalTiFlashWaitSummary .String ())
874
+ }
858
875
if ! totalTiFlashScanContext .Empty () {
859
876
buf .WriteString (", " + totalTiFlashScanContext .String ())
860
877
}
@@ -864,12 +881,12 @@ func (crs *CopRuntimeStats) String() string {
864
881
}
865
882
if totalTasks == 1 {
866
883
fmt .Fprintf (buf , "%v_task:{time:%v, loops:%d" , crs .storeType , FormatDuration (time .Duration (procTimes .GetPercentile (0 ))), totalLoops )
867
- printTiFlashScanContext ()
884
+ printTiFlashSpecificInfo ()
868
885
} else {
869
886
fmt .Fprintf (buf , "%v_task:{proc max:%v, min:%v, avg: %v, p80:%v, p95:%v, iters:%v, tasks:%v" ,
870
887
crs .storeType , FormatDuration (time .Duration (procTimes .GetMax ().GetFloat64 ())), FormatDuration (time .Duration (procTimes .GetMin ().GetFloat64 ())), FormatDuration (avgTime ),
871
888
FormatDuration (time .Duration (procTimes .GetPercentile (0.8 ))), FormatDuration (time .Duration (procTimes .GetPercentile (0.95 ))), totalLoops , totalTasks )
872
- printTiFlashScanContext ()
889
+ printTiFlashSpecificInfo ()
873
890
}
874
891
}
875
892
if ! isTiFlashCop {
@@ -1211,6 +1228,79 @@ func (context *TiFlashScanContext) Empty() bool {
1211
1228
return res
1212
1229
}
1213
1230
1231
+ // TiFlashWaitSummary is used to express all kinds of wait information in tiflash
1232
+ type TiFlashWaitSummary struct {
1233
+ // keep execution time to do merge work, always record the wait time with largest execution time
1234
+ executionTime uint64
1235
+ minTSOWaitTime uint64
1236
+ pipelineBreakerWaitTime uint64
1237
+ pipelineQueueWaitTime uint64
1238
+ }
1239
+
1240
+ // Clone implements the deep copy of * TiFlashWaitSummary
1241
+ func (waitSummary * TiFlashWaitSummary ) Clone () TiFlashWaitSummary {
1242
+ newSummary := TiFlashWaitSummary {
1243
+ executionTime : waitSummary .executionTime ,
1244
+ minTSOWaitTime : waitSummary .minTSOWaitTime ,
1245
+ pipelineBreakerWaitTime : waitSummary .pipelineBreakerWaitTime ,
1246
+ pipelineQueueWaitTime : waitSummary .pipelineQueueWaitTime ,
1247
+ }
1248
+ return newSummary
1249
+ }
1250
+
1251
+ // String dumps TiFlashWaitSummary info as string
1252
+ func (waitSummary * TiFlashWaitSummary ) String () string {
1253
+ if waitSummary .CanBeIgnored () {
1254
+ return ""
1255
+ }
1256
+ buf := bytes .NewBuffer (make ([]byte , 0 , 32 ))
1257
+ buf .WriteString ("tiflash_wait: {" )
1258
+ empty := true
1259
+ if waitSummary .minTSOWaitTime >= uint64 (time .Millisecond ) {
1260
+ buf .WriteString ("minTSO_wait: " )
1261
+ buf .WriteString (strconv .FormatInt (time .Duration (waitSummary .minTSOWaitTime ).Milliseconds (), 10 ))
1262
+ buf .WriteString ("ms" )
1263
+ empty = false
1264
+ }
1265
+ if waitSummary .pipelineBreakerWaitTime >= uint64 (time .Millisecond ) {
1266
+ if ! empty {
1267
+ buf .WriteString (", " )
1268
+ }
1269
+ buf .WriteString ("pipeline_breaker_wait: " )
1270
+ buf .WriteString (strconv .FormatInt (time .Duration (waitSummary .pipelineBreakerWaitTime ).Milliseconds (), 10 ))
1271
+ buf .WriteString ("ms" )
1272
+ empty = false
1273
+ }
1274
+ if waitSummary .pipelineQueueWaitTime >= uint64 (time .Millisecond ) {
1275
+ if ! empty {
1276
+ buf .WriteString (", " )
1277
+ }
1278
+ buf .WriteString ("pipeline_queue_wait: " )
1279
+ buf .WriteString (strconv .FormatInt (time .Duration (waitSummary .pipelineQueueWaitTime ).Milliseconds (), 10 ))
1280
+ buf .WriteString ("ms" )
1281
+ }
1282
+ buf .WriteString ("}" )
1283
+ return buf .String ()
1284
+ }
1285
+
1286
+ // Merge make sum to merge the information in TiFlashWaitSummary
1287
+ func (waitSummary * TiFlashWaitSummary ) Merge (other TiFlashWaitSummary ) {
1288
+ if waitSummary .executionTime < other .executionTime {
1289
+ waitSummary .executionTime = other .executionTime
1290
+ waitSummary .minTSOWaitTime = other .minTSOWaitTime
1291
+ waitSummary .pipelineBreakerWaitTime = other .pipelineBreakerWaitTime
1292
+ waitSummary .pipelineQueueWaitTime = other .pipelineQueueWaitTime
1293
+ }
1294
+ }
1295
+
1296
+ // CanBeIgnored check whether TiFlashWaitSummary can be ignored, not all tidb executors have significant tiflash wait summary
1297
+ func (waitSummary * TiFlashWaitSummary ) CanBeIgnored () bool {
1298
+ res := waitSummary .minTSOWaitTime < uint64 (time .Millisecond ) &&
1299
+ waitSummary .pipelineBreakerWaitTime < uint64 (time .Millisecond ) &&
1300
+ waitSummary .pipelineQueueWaitTime < uint64 (time .Millisecond )
1301
+ return res
1302
+ }
1303
+
1214
1304
// BasicRuntimeStats is the basic runtime stats.
1215
1305
type BasicRuntimeStats struct {
1216
1306
// executor's Next() called times.
0 commit comments