github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/stmtsummary/statement_summary_test.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package stmtsummary 15 16 import ( 17 "container/list" 18 "fmt" 19 "strconv" 20 "strings" 21 "sync" 22 "testing" 23 "time" 24 25 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 26 "github.com/whtcorpsinc/BerolinaSQL/auth" 27 . "github.com/whtcorpsinc/check" 28 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb" 29 "github.com/whtcorpsinc/milevadb/config" 30 "github.com/whtcorpsinc/milevadb/soliton/execdetails" 31 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 32 "github.com/whtcorpsinc/milevadb/types" 33 ) 34 35 var _ = Suite(&testStmtSummarySuite{}) 36 37 type testStmtSummarySuite struct { 38 ssMap *stmtSummaryByDigestMap 39 } 40 41 func emptyCausetGenerator() string { 42 return "" 43 } 44 45 func fakeCausetDigestGenerator() string { 46 return "point_get" 47 } 48 49 func (s *testStmtSummarySuite) SetUpSuite(c *C) { 50 s.ssMap = newStmtSummaryByDigestMap() 51 s.ssMap.SetEnabled("1", false) 52 s.ssMap.SetRefreshInterval("1800", false) 53 s.ssMap.SetHistorySize("24", false) 54 } 55 56 func TestT(t *testing.T) { 57 CustomVerboseFlag = true 58 TestingT(t) 59 } 60 61 // Test stmtSummaryByDigest.AddStatement. 62 func (s *testStmtSummarySuite) TestAddStatement(c *C) { 63 s.ssMap.Clear() 64 now := time.Now().Unix() 65 s.ssMap.beginTimeForCurInterval = now + 60 66 67 blocks := []stmtctx.BlockEntry{{EDB: "db1", Block: "tb1"}, {EDB: "db2", Block: "tb2"}} 68 indexes := []string{"a", "b"} 69 70 // first memex 71 stmtInterDircInfo1 := generateAnyInterDircInfo() 72 stmtInterDircInfo1.InterDircDetail.CommitDetail.Mu.BackoffTypes = make([]fmt.Stringer, 0) 73 key := &stmtSummaryByDigestKey{ 74 schemaName: stmtInterDircInfo1.SchemaName, 75 digest: stmtInterDircInfo1.Digest, 76 planDigest: stmtInterDircInfo1.CausetDigest, 77 } 78 expectedSummaryElement := stmtSummaryByDigestElement{ 79 beginTime: now + 60, 80 endTime: now + 1860, 81 sampleALLEGROSQL: stmtInterDircInfo1.OriginalALLEGROSQL, 82 sampleCauset: stmtInterDircInfo1.CausetGenerator(), 83 indexNames: stmtInterDircInfo1.StmtCtx.IndexNames, 84 execCount: 1, 85 sumLatency: stmtInterDircInfo1.TotalLatency, 86 maxLatency: stmtInterDircInfo1.TotalLatency, 87 minLatency: stmtInterDircInfo1.TotalLatency, 88 sumParseLatency: stmtInterDircInfo1.ParseLatency, 89 maxParseLatency: stmtInterDircInfo1.ParseLatency, 90 sumCompileLatency: stmtInterDircInfo1.CompileLatency, 91 maxCompileLatency: stmtInterDircInfo1.CompileLatency, 92 sumNumCausetTasks: int64(stmtInterDircInfo1.CausetTasks.NumCausetTasks), 93 maxCopProcessTime: stmtInterDircInfo1.CausetTasks.MaxProcessTime, 94 maxCopProcessAddress: stmtInterDircInfo1.CausetTasks.MaxProcessAddress, 95 maxCopWaitTime: stmtInterDircInfo1.CausetTasks.MaxWaitTime, 96 maxCopWaitAddress: stmtInterDircInfo1.CausetTasks.MaxWaitAddress, 97 sumProcessTime: stmtInterDircInfo1.InterDircDetail.ProcessTime, 98 maxProcessTime: stmtInterDircInfo1.InterDircDetail.ProcessTime, 99 sumWaitTime: stmtInterDircInfo1.InterDircDetail.WaitTime, 100 maxWaitTime: stmtInterDircInfo1.InterDircDetail.WaitTime, 101 sumBackoffTime: stmtInterDircInfo1.InterDircDetail.BackoffTime, 102 maxBackoffTime: stmtInterDircInfo1.InterDircDetail.BackoffTime, 103 sumTotalKeys: stmtInterDircInfo1.InterDircDetail.TotalKeys, 104 maxTotalKeys: stmtInterDircInfo1.InterDircDetail.TotalKeys, 105 sumProcessedKeys: stmtInterDircInfo1.InterDircDetail.ProcessedKeys, 106 maxProcessedKeys: stmtInterDircInfo1.InterDircDetail.ProcessedKeys, 107 sumGetCommitTsTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime, 108 maxGetCommitTsTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime, 109 sumPrewriteTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime, 110 maxPrewriteTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime, 111 sumCommitTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime, 112 maxCommitTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime, 113 sumLocalLatchTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime, 114 maxLocalLatchTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime, 115 sumCommitBackoffTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime, 116 maxCommitBackoffTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime, 117 sumResolveLockTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime, 118 maxResolveLockTime: stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime, 119 sumWriteKeys: int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys), 120 maxWriteKeys: stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys, 121 sumWriteSize: int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize), 122 maxWriteSize: stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize, 123 sumPrewriteRegionNum: int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum), 124 maxPrewriteRegionNum: stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum, 125 sumTxnRetry: int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry), 126 maxTxnRetry: stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry, 127 backoffTypes: make(map[fmt.Stringer]int), 128 sumMem: stmtInterDircInfo1.MemMax, 129 maxMem: stmtInterDircInfo1.MemMax, 130 sumDisk: stmtInterDircInfo1.DiskMax, 131 maxDisk: stmtInterDircInfo1.DiskMax, 132 sumAffectedRows: stmtInterDircInfo1.StmtCtx.AffectedRows(), 133 firstSeen: stmtInterDircInfo1.StartTime, 134 lastSeen: stmtInterDircInfo1.StartTime, 135 } 136 history := list.New() 137 history.PushBack(&expectedSummaryElement) 138 expectedSummary := stmtSummaryByDigest{ 139 schemaName: stmtInterDircInfo1.SchemaName, 140 stmtType: stmtInterDircInfo1.StmtCtx.StmtType, 141 digest: stmtInterDircInfo1.Digest, 142 normalizedALLEGROSQL: stmtInterDircInfo1.NormalizedALLEGROSQL, 143 planDigest: stmtInterDircInfo1.CausetDigest, 144 blockNames: "db1.tb1,db2.tb2", 145 history: history, 146 } 147 s.ssMap.AddStatement(stmtInterDircInfo1) 148 summary, ok := s.ssMap.summaryMap.Get(key) 149 c.Assert(ok, IsTrue) 150 c.Assert(matchStmtSummaryByDigest(summary.(*stmtSummaryByDigest), &expectedSummary), IsTrue) 151 152 // Second memex is similar with the first memex, and its values are 153 // greater than that of the first memex. 154 stmtInterDircInfo2 := &StmtInterDircInfo{ 155 SchemaName: "schema_name", 156 OriginalALLEGROSQL: "original_sql2", 157 NormalizedALLEGROSQL: "normalized_sql", 158 Digest: "digest", 159 CausetDigest: "plan_digest", 160 CausetGenerator: emptyCausetGenerator, 161 User: "user2", 162 TotalLatency: 20000, 163 ParseLatency: 200, 164 CompileLatency: 2000, 165 CausetTasks: &stmtctx.CausetTasksDetails{ 166 NumCausetTasks: 20, 167 AvgProcessTime: 2000, 168 P90ProcessTime: 20000, 169 MaxProcessAddress: "200", 170 MaxProcessTime: 25000, 171 AvgWaitTime: 200, 172 P90WaitTime: 2000, 173 MaxWaitAddress: "201", 174 MaxWaitTime: 2500, 175 }, 176 InterDircDetail: &execdetails.InterDircDetails{ 177 CalleeAddress: "202", 178 ProcessTime: 1500, 179 WaitTime: 150, 180 BackoffTime: 180, 181 RequestCount: 20, 182 TotalKeys: 6000, 183 ProcessedKeys: 1500, 184 CommitDetail: &execdetails.CommitDetails{ 185 GetCommitTsTime: 500, 186 PrewriteTime: 50000, 187 CommitTime: 5000, 188 LocalLatchTime: 50, 189 CommitBackoffTime: 1000, 190 Mu: struct { 191 sync.Mutex 192 BackoffTypes []fmt.Stringer 193 }{ 194 BackoffTypes: []fmt.Stringer{einsteindb.BoTxnLock}, 195 }, 196 ResolveLockTime: 10000, 197 WriteKeys: 100000, 198 WriteSize: 1000000, 199 PrewriteRegionNum: 100, 200 TxnRetry: 10, 201 }, 202 }, 203 StmtCtx: &stmtctx.StatementContext{ 204 StmtType: "Select", 205 Blocks: blocks, 206 IndexNames: indexes, 207 }, 208 MemMax: 20000, 209 DiskMax: 20000, 210 StartTime: time.Date(2020, 1, 1, 10, 10, 20, 10, time.UTC), 211 Succeed: true, 212 } 213 stmtInterDircInfo2.StmtCtx.AddAffectedRows(200) 214 expectedSummaryElement.execCount++ 215 expectedSummaryElement.sumLatency += stmtInterDircInfo2.TotalLatency 216 expectedSummaryElement.maxLatency = stmtInterDircInfo2.TotalLatency 217 expectedSummaryElement.sumParseLatency += stmtInterDircInfo2.ParseLatency 218 expectedSummaryElement.maxParseLatency = stmtInterDircInfo2.ParseLatency 219 expectedSummaryElement.sumCompileLatency += stmtInterDircInfo2.CompileLatency 220 expectedSummaryElement.maxCompileLatency = stmtInterDircInfo2.CompileLatency 221 expectedSummaryElement.sumNumCausetTasks += int64(stmtInterDircInfo2.CausetTasks.NumCausetTasks) 222 expectedSummaryElement.maxCopProcessTime = stmtInterDircInfo2.CausetTasks.MaxProcessTime 223 expectedSummaryElement.maxCopProcessAddress = stmtInterDircInfo2.CausetTasks.MaxProcessAddress 224 expectedSummaryElement.maxCopWaitTime = stmtInterDircInfo2.CausetTasks.MaxWaitTime 225 expectedSummaryElement.maxCopWaitAddress = stmtInterDircInfo2.CausetTasks.MaxWaitAddress 226 expectedSummaryElement.sumProcessTime += stmtInterDircInfo2.InterDircDetail.ProcessTime 227 expectedSummaryElement.maxProcessTime = stmtInterDircInfo2.InterDircDetail.ProcessTime 228 expectedSummaryElement.sumWaitTime += stmtInterDircInfo2.InterDircDetail.WaitTime 229 expectedSummaryElement.maxWaitTime = stmtInterDircInfo2.InterDircDetail.WaitTime 230 expectedSummaryElement.sumBackoffTime += stmtInterDircInfo2.InterDircDetail.BackoffTime 231 expectedSummaryElement.maxBackoffTime = stmtInterDircInfo2.InterDircDetail.BackoffTime 232 expectedSummaryElement.sumTotalKeys += stmtInterDircInfo2.InterDircDetail.TotalKeys 233 expectedSummaryElement.maxTotalKeys = stmtInterDircInfo2.InterDircDetail.TotalKeys 234 expectedSummaryElement.sumProcessedKeys += stmtInterDircInfo2.InterDircDetail.ProcessedKeys 235 expectedSummaryElement.maxProcessedKeys = stmtInterDircInfo2.InterDircDetail.ProcessedKeys 236 expectedSummaryElement.sumGetCommitTsTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.GetCommitTsTime 237 expectedSummaryElement.maxGetCommitTsTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.GetCommitTsTime 238 expectedSummaryElement.sumPrewriteTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteTime 239 expectedSummaryElement.maxPrewriteTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteTime 240 expectedSummaryElement.sumCommitTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitTime 241 expectedSummaryElement.maxCommitTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitTime 242 expectedSummaryElement.sumLocalLatchTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.LocalLatchTime 243 expectedSummaryElement.maxLocalLatchTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.LocalLatchTime 244 expectedSummaryElement.sumCommitBackoffTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitBackoffTime 245 expectedSummaryElement.maxCommitBackoffTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.CommitBackoffTime 246 expectedSummaryElement.sumResolveLockTime += stmtInterDircInfo2.InterDircDetail.CommitDetail.ResolveLockTime 247 expectedSummaryElement.maxResolveLockTime = stmtInterDircInfo2.InterDircDetail.CommitDetail.ResolveLockTime 248 expectedSummaryElement.sumWriteKeys += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteKeys) 249 expectedSummaryElement.maxWriteKeys = stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteKeys 250 expectedSummaryElement.sumWriteSize += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteSize) 251 expectedSummaryElement.maxWriteSize = stmtInterDircInfo2.InterDircDetail.CommitDetail.WriteSize 252 expectedSummaryElement.sumPrewriteRegionNum += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteRegionNum) 253 expectedSummaryElement.maxPrewriteRegionNum = stmtInterDircInfo2.InterDircDetail.CommitDetail.PrewriteRegionNum 254 expectedSummaryElement.sumTxnRetry += int64(stmtInterDircInfo2.InterDircDetail.CommitDetail.TxnRetry) 255 expectedSummaryElement.maxTxnRetry = stmtInterDircInfo2.InterDircDetail.CommitDetail.TxnRetry 256 expectedSummaryElement.sumBackoffTimes += 1 257 expectedSummaryElement.backoffTypes[einsteindb.BoTxnLock] = 1 258 expectedSummaryElement.sumMem += stmtInterDircInfo2.MemMax 259 expectedSummaryElement.maxMem = stmtInterDircInfo2.MemMax 260 expectedSummaryElement.sumDisk += stmtInterDircInfo2.DiskMax 261 expectedSummaryElement.maxDisk = stmtInterDircInfo2.DiskMax 262 expectedSummaryElement.sumAffectedRows += stmtInterDircInfo2.StmtCtx.AffectedRows() 263 expectedSummaryElement.lastSeen = stmtInterDircInfo2.StartTime 264 265 s.ssMap.AddStatement(stmtInterDircInfo2) 266 summary, ok = s.ssMap.summaryMap.Get(key) 267 c.Assert(ok, IsTrue) 268 c.Assert(matchStmtSummaryByDigest(summary.(*stmtSummaryByDigest), &expectedSummary), IsTrue) 269 270 // Third memex is similar with the first memex, and its values are 271 // less than that of the first memex. 272 stmtInterDircInfo3 := &StmtInterDircInfo{ 273 SchemaName: "schema_name", 274 OriginalALLEGROSQL: "original_sql3", 275 NormalizedALLEGROSQL: "normalized_sql", 276 Digest: "digest", 277 CausetDigest: "plan_digest", 278 CausetGenerator: emptyCausetGenerator, 279 User: "user3", 280 TotalLatency: 1000, 281 ParseLatency: 50, 282 CompileLatency: 500, 283 CausetTasks: &stmtctx.CausetTasksDetails{ 284 NumCausetTasks: 2, 285 AvgProcessTime: 100, 286 P90ProcessTime: 300, 287 MaxProcessAddress: "300", 288 MaxProcessTime: 350, 289 AvgWaitTime: 20, 290 P90WaitTime: 200, 291 MaxWaitAddress: "301", 292 MaxWaitTime: 250, 293 }, 294 InterDircDetail: &execdetails.InterDircDetails{ 295 CalleeAddress: "302", 296 ProcessTime: 150, 297 WaitTime: 15, 298 BackoffTime: 18, 299 RequestCount: 2, 300 TotalKeys: 600, 301 ProcessedKeys: 150, 302 CommitDetail: &execdetails.CommitDetails{ 303 GetCommitTsTime: 50, 304 PrewriteTime: 5000, 305 CommitTime: 500, 306 LocalLatchTime: 5, 307 CommitBackoffTime: 100, 308 Mu: struct { 309 sync.Mutex 310 BackoffTypes []fmt.Stringer 311 }{ 312 BackoffTypes: []fmt.Stringer{einsteindb.BoTxnLock}, 313 }, 314 ResolveLockTime: 1000, 315 WriteKeys: 10000, 316 WriteSize: 100000, 317 PrewriteRegionNum: 10, 318 TxnRetry: 1, 319 }, 320 }, 321 StmtCtx: &stmtctx.StatementContext{ 322 StmtType: "Select", 323 Blocks: blocks, 324 IndexNames: indexes, 325 }, 326 MemMax: 200, 327 DiskMax: 200, 328 StartTime: time.Date(2020, 1, 1, 10, 10, 0, 10, time.UTC), 329 Succeed: true, 330 } 331 stmtInterDircInfo3.StmtCtx.AddAffectedRows(20000) 332 expectedSummaryElement.execCount++ 333 expectedSummaryElement.sumLatency += stmtInterDircInfo3.TotalLatency 334 expectedSummaryElement.minLatency = stmtInterDircInfo3.TotalLatency 335 expectedSummaryElement.sumParseLatency += stmtInterDircInfo3.ParseLatency 336 expectedSummaryElement.sumCompileLatency += stmtInterDircInfo3.CompileLatency 337 expectedSummaryElement.sumNumCausetTasks += int64(stmtInterDircInfo3.CausetTasks.NumCausetTasks) 338 expectedSummaryElement.sumProcessTime += stmtInterDircInfo3.InterDircDetail.ProcessTime 339 expectedSummaryElement.sumWaitTime += stmtInterDircInfo3.InterDircDetail.WaitTime 340 expectedSummaryElement.sumBackoffTime += stmtInterDircInfo3.InterDircDetail.BackoffTime 341 expectedSummaryElement.sumTotalKeys += stmtInterDircInfo3.InterDircDetail.TotalKeys 342 expectedSummaryElement.sumProcessedKeys += stmtInterDircInfo3.InterDircDetail.ProcessedKeys 343 expectedSummaryElement.sumGetCommitTsTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.GetCommitTsTime 344 expectedSummaryElement.sumPrewriteTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.PrewriteTime 345 expectedSummaryElement.sumCommitTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.CommitTime 346 expectedSummaryElement.sumLocalLatchTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.LocalLatchTime 347 expectedSummaryElement.sumCommitBackoffTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.CommitBackoffTime 348 expectedSummaryElement.sumResolveLockTime += stmtInterDircInfo3.InterDircDetail.CommitDetail.ResolveLockTime 349 expectedSummaryElement.sumWriteKeys += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.WriteKeys) 350 expectedSummaryElement.sumWriteSize += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.WriteSize) 351 expectedSummaryElement.sumPrewriteRegionNum += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.PrewriteRegionNum) 352 expectedSummaryElement.sumTxnRetry += int64(stmtInterDircInfo3.InterDircDetail.CommitDetail.TxnRetry) 353 expectedSummaryElement.sumBackoffTimes += 1 354 expectedSummaryElement.backoffTypes[einsteindb.BoTxnLock] = 2 355 expectedSummaryElement.sumMem += stmtInterDircInfo3.MemMax 356 expectedSummaryElement.sumDisk += stmtInterDircInfo3.DiskMax 357 expectedSummaryElement.sumAffectedRows += stmtInterDircInfo3.StmtCtx.AffectedRows() 358 expectedSummaryElement.firstSeen = stmtInterDircInfo3.StartTime 359 360 s.ssMap.AddStatement(stmtInterDircInfo3) 361 summary, ok = s.ssMap.summaryMap.Get(key) 362 c.Assert(ok, IsTrue) 363 c.Assert(matchStmtSummaryByDigest(summary.(*stmtSummaryByDigest), &expectedSummary), IsTrue) 364 365 // Fourth memex is in a different schemaReplicant. 366 stmtInterDircInfo4 := stmtInterDircInfo1 367 stmtInterDircInfo4.SchemaName = "schema2" 368 stmtInterDircInfo4.InterDircDetail.CommitDetail = nil 369 key = &stmtSummaryByDigestKey{ 370 schemaName: stmtInterDircInfo4.SchemaName, 371 digest: stmtInterDircInfo4.Digest, 372 planDigest: stmtInterDircInfo4.CausetDigest, 373 } 374 s.ssMap.AddStatement(stmtInterDircInfo4) 375 c.Assert(s.ssMap.summaryMap.Size(), Equals, 2) 376 _, ok = s.ssMap.summaryMap.Get(key) 377 c.Assert(ok, IsTrue) 378 379 // Fifth memex has a different digest. 380 stmtInterDircInfo5 := stmtInterDircInfo1 381 stmtInterDircInfo5.Digest = "digest2" 382 key = &stmtSummaryByDigestKey{ 383 schemaName: stmtInterDircInfo5.SchemaName, 384 digest: stmtInterDircInfo5.Digest, 385 planDigest: stmtInterDircInfo4.CausetDigest, 386 } 387 s.ssMap.AddStatement(stmtInterDircInfo5) 388 c.Assert(s.ssMap.summaryMap.Size(), Equals, 3) 389 _, ok = s.ssMap.summaryMap.Get(key) 390 c.Assert(ok, IsTrue) 391 392 // Sixth memex has a different plan digest. 393 stmtInterDircInfo6 := stmtInterDircInfo1 394 stmtInterDircInfo6.CausetDigest = "plan_digest2" 395 key = &stmtSummaryByDigestKey{ 396 schemaName: stmtInterDircInfo6.SchemaName, 397 digest: stmtInterDircInfo6.Digest, 398 planDigest: stmtInterDircInfo6.CausetDigest, 399 } 400 s.ssMap.AddStatement(stmtInterDircInfo6) 401 c.Assert(s.ssMap.summaryMap.Size(), Equals, 4) 402 _, ok = s.ssMap.summaryMap.Get(key) 403 c.Assert(ok, IsTrue) 404 } 405 406 func matchStmtSummaryByDigest(first, second *stmtSummaryByDigest) bool { 407 if first.schemaName != second.schemaName || 408 first.digest != second.digest || 409 first.normalizedALLEGROSQL != second.normalizedALLEGROSQL || 410 first.planDigest != second.planDigest || 411 first.blockNames != second.blockNames || 412 !strings.EqualFold(first.stmtType, second.stmtType) { 413 return false 414 } 415 if first.history.Len() != second.history.Len() { 416 return false 417 } 418 ele1 := first.history.Front() 419 ele2 := second.history.Front() 420 for { 421 if ele1 == nil { 422 break 423 } 424 ssElement1 := ele1.Value.(*stmtSummaryByDigestElement) 425 ssElement2 := ele2.Value.(*stmtSummaryByDigestElement) 426 if ssElement1.beginTime != ssElement2.beginTime || 427 ssElement1.endTime != ssElement2.endTime || 428 ssElement1.sampleALLEGROSQL != ssElement2.sampleALLEGROSQL || 429 ssElement1.sampleCauset != ssElement2.sampleCauset || 430 ssElement1.prevALLEGROSQL != ssElement2.prevALLEGROSQL || 431 ssElement1.execCount != ssElement2.execCount || 432 ssElement1.sumErrors != ssElement2.sumErrors || 433 ssElement1.sumWarnings != ssElement2.sumWarnings || 434 ssElement1.sumLatency != ssElement2.sumLatency || 435 ssElement1.maxLatency != ssElement2.maxLatency || 436 ssElement1.minLatency != ssElement2.minLatency || 437 ssElement1.sumParseLatency != ssElement2.sumParseLatency || 438 ssElement1.maxParseLatency != ssElement2.maxParseLatency || 439 ssElement1.sumCompileLatency != ssElement2.sumCompileLatency || 440 ssElement1.maxCompileLatency != ssElement2.maxCompileLatency || 441 ssElement1.sumNumCausetTasks != ssElement2.sumNumCausetTasks || 442 ssElement1.maxCopProcessTime != ssElement2.maxCopProcessTime || 443 ssElement1.maxCopProcessAddress != ssElement2.maxCopProcessAddress || 444 ssElement1.maxCopWaitTime != ssElement2.maxCopWaitTime || 445 ssElement1.maxCopWaitAddress != ssElement2.maxCopWaitAddress || 446 ssElement1.sumProcessTime != ssElement2.sumProcessTime || 447 ssElement1.maxProcessTime != ssElement2.maxProcessTime || 448 ssElement1.sumWaitTime != ssElement2.sumWaitTime || 449 ssElement1.maxWaitTime != ssElement2.maxWaitTime || 450 ssElement1.sumBackoffTime != ssElement2.sumBackoffTime || 451 ssElement1.maxBackoffTime != ssElement2.maxBackoffTime || 452 ssElement1.sumTotalKeys != ssElement2.sumTotalKeys || 453 ssElement1.maxTotalKeys != ssElement2.maxTotalKeys || 454 ssElement1.sumProcessedKeys != ssElement2.sumProcessedKeys || 455 ssElement1.maxProcessedKeys != ssElement2.maxProcessedKeys || 456 ssElement1.sumGetCommitTsTime != ssElement2.sumGetCommitTsTime || 457 ssElement1.maxGetCommitTsTime != ssElement2.maxGetCommitTsTime || 458 ssElement1.sumPrewriteTime != ssElement2.sumPrewriteTime || 459 ssElement1.maxPrewriteTime != ssElement2.maxPrewriteTime || 460 ssElement1.sumCommitTime != ssElement2.sumCommitTime || 461 ssElement1.maxCommitTime != ssElement2.maxCommitTime || 462 ssElement1.sumLocalLatchTime != ssElement2.sumLocalLatchTime || 463 ssElement1.maxLocalLatchTime != ssElement2.maxLocalLatchTime || 464 ssElement1.sumCommitBackoffTime != ssElement2.sumCommitBackoffTime || 465 ssElement1.maxCommitBackoffTime != ssElement2.maxCommitBackoffTime || 466 ssElement1.sumResolveLockTime != ssElement2.sumResolveLockTime || 467 ssElement1.maxResolveLockTime != ssElement2.maxResolveLockTime || 468 ssElement1.sumWriteKeys != ssElement2.sumWriteKeys || 469 ssElement1.maxWriteKeys != ssElement2.maxWriteKeys || 470 ssElement1.sumWriteSize != ssElement2.sumWriteSize || 471 ssElement1.maxWriteSize != ssElement2.maxWriteSize || 472 ssElement1.sumPrewriteRegionNum != ssElement2.sumPrewriteRegionNum || 473 ssElement1.maxPrewriteRegionNum != ssElement2.maxPrewriteRegionNum || 474 ssElement1.sumTxnRetry != ssElement2.sumTxnRetry || 475 ssElement1.maxTxnRetry != ssElement2.maxTxnRetry || 476 ssElement1.sumBackoffTimes != ssElement2.sumBackoffTimes || 477 ssElement1.sumMem != ssElement2.sumMem || 478 ssElement1.maxMem != ssElement2.maxMem || 479 ssElement1.sumAffectedRows != ssElement2.sumAffectedRows || 480 ssElement1.firstSeen != ssElement2.firstSeen || 481 ssElement1.lastSeen != ssElement2.lastSeen { 482 return false 483 } 484 if len(ssElement1.backoffTypes) != len(ssElement2.backoffTypes) { 485 return false 486 } 487 for key, value1 := range ssElement1.backoffTypes { 488 value2, ok := ssElement2.backoffTypes[key] 489 if !ok || value1 != value2 { 490 return false 491 } 492 } 493 if len(ssElement1.indexNames) != len(ssElement2.indexNames) { 494 return false 495 } 496 for key, value1 := range ssElement1.indexNames { 497 if value1 != ssElement2.indexNames[key] { 498 return false 499 } 500 } 501 ele1 = ele1.Next() 502 ele2 = ele2.Next() 503 } 504 return true 505 } 506 507 func match(c *C, event []types.Causet, expected ...interface{}) { 508 c.Assert(len(event), Equals, len(expected)) 509 for i := range event { 510 got := fmt.Sprintf("%v", event[i].GetValue()) 511 need := fmt.Sprintf("%v", expected[i]) 512 c.Assert(got, Equals, need) 513 } 514 } 515 516 func generateAnyInterDircInfo() *StmtInterDircInfo { 517 blocks := []stmtctx.BlockEntry{{EDB: "db1", Block: "tb1"}, {EDB: "db2", Block: "tb2"}} 518 indexes := []string{"a"} 519 stmtInterDircInfo := &StmtInterDircInfo{ 520 SchemaName: "schema_name", 521 OriginalALLEGROSQL: "original_sql1", 522 NormalizedALLEGROSQL: "normalized_sql", 523 Digest: "digest", 524 CausetDigest: "plan_digest", 525 CausetGenerator: emptyCausetGenerator, 526 User: "user", 527 TotalLatency: 10000, 528 ParseLatency: 100, 529 CompileLatency: 1000, 530 CausetTasks: &stmtctx.CausetTasksDetails{ 531 NumCausetTasks: 10, 532 AvgProcessTime: 1000, 533 P90ProcessTime: 10000, 534 MaxProcessAddress: "127", 535 MaxProcessTime: 15000, 536 AvgWaitTime: 100, 537 P90WaitTime: 1000, 538 MaxWaitAddress: "128", 539 MaxWaitTime: 1500, 540 }, 541 InterDircDetail: &execdetails.InterDircDetails{ 542 CalleeAddress: "129", 543 ProcessTime: 500, 544 WaitTime: 50, 545 BackoffTime: 80, 546 RequestCount: 10, 547 TotalKeys: 1000, 548 ProcessedKeys: 500, 549 CommitDetail: &execdetails.CommitDetails{ 550 GetCommitTsTime: 100, 551 PrewriteTime: 10000, 552 CommitTime: 1000, 553 LocalLatchTime: 10, 554 CommitBackoffTime: 200, 555 Mu: struct { 556 sync.Mutex 557 BackoffTypes []fmt.Stringer 558 }{ 559 BackoffTypes: []fmt.Stringer{einsteindb.BoTxnLock}, 560 }, 561 ResolveLockTime: 2000, 562 WriteKeys: 20000, 563 WriteSize: 200000, 564 PrewriteRegionNum: 20, 565 TxnRetry: 2, 566 }, 567 }, 568 StmtCtx: &stmtctx.StatementContext{ 569 StmtType: "Select", 570 Blocks: blocks, 571 IndexNames: indexes, 572 }, 573 MemMax: 10000, 574 DiskMax: 10000, 575 StartTime: time.Date(2020, 1, 1, 10, 10, 10, 10, time.UTC), 576 Succeed: true, 577 } 578 stmtInterDircInfo.StmtCtx.AddAffectedRows(10000) 579 return stmtInterDircInfo 580 } 581 582 // Test stmtSummaryByDigest.ToCauset. 583 func (s *testStmtSummarySuite) TestToCauset(c *C) { 584 s.ssMap.Clear() 585 now := time.Now().Unix() 586 // to disable expiration 587 s.ssMap.beginTimeForCurInterval = now + 60 588 589 stmtInterDircInfo1 := generateAnyInterDircInfo() 590 s.ssMap.AddStatement(stmtInterDircInfo1) 591 datums := s.ssMap.ToCurrentCauset(nil, true) 592 c.Assert(len(datums), Equals, 1) 593 n := types.NewTime(types.FromGoTime(time.Unix(s.ssMap.beginTimeForCurInterval, 0)), allegrosql.TypeTimestamp, types.DefaultFsp) 594 e := types.NewTime(types.FromGoTime(time.Unix(s.ssMap.beginTimeForCurInterval+1800, 0)), allegrosql.TypeTimestamp, types.DefaultFsp) 595 t := types.NewTime(types.FromGoTime(stmtInterDircInfo1.StartTime), allegrosql.TypeTimestamp, types.DefaultFsp) 596 expectedCauset := []interface{}{n, e, "Select", stmtInterDircInfo1.SchemaName, stmtInterDircInfo1.Digest, stmtInterDircInfo1.NormalizedALLEGROSQL, 597 "db1.tb1,db2.tb2", "a", stmtInterDircInfo1.User, 1, 0, 0, int64(stmtInterDircInfo1.TotalLatency), 598 int64(stmtInterDircInfo1.TotalLatency), int64(stmtInterDircInfo1.TotalLatency), int64(stmtInterDircInfo1.TotalLatency), 599 int64(stmtInterDircInfo1.ParseLatency), int64(stmtInterDircInfo1.ParseLatency), int64(stmtInterDircInfo1.CompileLatency), 600 int64(stmtInterDircInfo1.CompileLatency), stmtInterDircInfo1.CausetTasks.NumCausetTasks, int64(stmtInterDircInfo1.CausetTasks.MaxProcessTime), 601 stmtInterDircInfo1.CausetTasks.MaxProcessAddress, int64(stmtInterDircInfo1.CausetTasks.MaxWaitTime), 602 stmtInterDircInfo1.CausetTasks.MaxWaitAddress, int64(stmtInterDircInfo1.InterDircDetail.ProcessTime), int64(stmtInterDircInfo1.InterDircDetail.ProcessTime), 603 int64(stmtInterDircInfo1.InterDircDetail.WaitTime), int64(stmtInterDircInfo1.InterDircDetail.WaitTime), int64(stmtInterDircInfo1.InterDircDetail.BackoffTime), 604 int64(stmtInterDircInfo1.InterDircDetail.BackoffTime), stmtInterDircInfo1.InterDircDetail.TotalKeys, stmtInterDircInfo1.InterDircDetail.TotalKeys, 605 stmtInterDircInfo1.InterDircDetail.ProcessedKeys, stmtInterDircInfo1.InterDircDetail.ProcessedKeys, 606 int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteTime), 607 int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitTime), 608 int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.GetCommitTsTime), 609 stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime, stmtInterDircInfo1.InterDircDetail.CommitDetail.CommitBackoffTime, 610 stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime, stmtInterDircInfo1.InterDircDetail.CommitDetail.ResolveLockTime, 611 int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime), int64(stmtInterDircInfo1.InterDircDetail.CommitDetail.LocalLatchTime), 612 stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys, stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteKeys, 613 stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize, stmtInterDircInfo1.InterDircDetail.CommitDetail.WriteSize, 614 stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum, stmtInterDircInfo1.InterDircDetail.CommitDetail.PrewriteRegionNum, 615 stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry, stmtInterDircInfo1.InterDircDetail.CommitDetail.TxnRetry, 0, 0, 1, 616 "txnLock:1", stmtInterDircInfo1.MemMax, stmtInterDircInfo1.MemMax, stmtInterDircInfo1.DiskMax, stmtInterDircInfo1.DiskMax, stmtInterDircInfo1.StmtCtx.AffectedRows(), 617 t, t, 0, 0, stmtInterDircInfo1.OriginalALLEGROSQL, stmtInterDircInfo1.PrevALLEGROSQL, "plan_digest", ""} 618 match(c, datums[0], expectedCauset...) 619 datums = s.ssMap.ToHistoryCauset(nil, true) 620 c.Assert(len(datums), Equals, 1) 621 match(c, datums[0], expectedCauset...) 622 } 623 624 // Test AddStatement and ToCauset parallel. 625 func (s *testStmtSummarySuite) TestAddStatementParallel(c *C) { 626 s.ssMap.Clear() 627 now := time.Now().Unix() 628 // to disable expiration 629 s.ssMap.beginTimeForCurInterval = now + 60 630 631 threads := 8 632 loops := 32 633 wg := sync.WaitGroup{} 634 wg.Add(threads) 635 636 addStmtFunc := func() { 637 defer wg.Done() 638 stmtInterDircInfo1 := generateAnyInterDircInfo() 639 640 // Add 32 times with different digest. 641 for i := 0; i < loops; i++ { 642 stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i) 643 s.ssMap.AddStatement(stmtInterDircInfo1) 644 } 645 646 // There would be 32 summaries. 647 datums := s.ssMap.ToCurrentCauset(nil, true) 648 c.Assert(len(datums), Equals, loops) 649 } 650 651 for i := 0; i < threads; i++ { 652 go addStmtFunc() 653 } 654 wg.Wait() 655 656 datums := s.ssMap.ToCurrentCauset(nil, true) 657 c.Assert(len(datums), Equals, loops) 658 } 659 660 // Test max number of memex count. 661 func (s *testStmtSummarySuite) TestMaxStmtCount(c *C) { 662 s.ssMap.Clear() 663 now := time.Now().Unix() 664 // to disable expiration 665 s.ssMap.beginTimeForCurInterval = now + 60 666 667 // Test the original value and modify it. 668 maxStmtCount := s.ssMap.maxStmtCount() 669 c.Assert(maxStmtCount, Equals, int(config.GetGlobalConfig().StmtSummary.MaxStmtCount)) 670 c.Assert(s.ssMap.SetMaxStmtCount("10", false), IsNil) 671 c.Assert(s.ssMap.maxStmtCount(), Equals, 10) 672 defer func() { 673 c.Assert(s.ssMap.SetMaxStmtCount("", false), IsNil) 674 c.Assert(s.ssMap.SetMaxStmtCount("", true), IsNil) 675 c.Assert(maxStmtCount, Equals, int(config.GetGlobalConfig().StmtSummary.MaxStmtCount)) 676 }() 677 678 // 100 digests 679 stmtInterDircInfo1 := generateAnyInterDircInfo() 680 loops := 100 681 for i := 0; i < loops; i++ { 682 stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i) 683 s.ssMap.AddStatement(stmtInterDircInfo1) 684 } 685 686 // Summary count should be MaxStmtCount. 687 sm := s.ssMap.summaryMap 688 c.Assert(sm.Size(), Equals, 10) 689 690 // LRU cache should work. 691 for i := loops - 10; i < loops; i++ { 692 key := &stmtSummaryByDigestKey{ 693 schemaName: stmtInterDircInfo1.SchemaName, 694 digest: fmt.Sprintf("digest%d", i), 695 planDigest: stmtInterDircInfo1.CausetDigest, 696 } 697 _, ok := sm.Get(key) 698 c.Assert(ok, IsTrue) 699 } 700 701 // Change to a bigger value. 702 c.Assert(s.ssMap.SetMaxStmtCount("50", true), IsNil) 703 for i := 0; i < loops; i++ { 704 stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i) 705 s.ssMap.AddStatement(stmtInterDircInfo1) 706 } 707 c.Assert(sm.Size(), Equals, 50) 708 709 // Change to a smaller value. 710 c.Assert(s.ssMap.SetMaxStmtCount("10", true), IsNil) 711 for i := 0; i < loops; i++ { 712 stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i) 713 s.ssMap.AddStatement(stmtInterDircInfo1) 714 } 715 c.Assert(sm.Size(), Equals, 10) 716 } 717 718 // Test max length of normalized and sample ALLEGROALLEGROSQL. 719 func (s *testStmtSummarySuite) TestMaxALLEGROSQLLength(c *C) { 720 s.ssMap.Clear() 721 now := time.Now().Unix() 722 // to disable expiration 723 s.ssMap.beginTimeForCurInterval = now + 60 724 725 // Test the original value and modify it. 726 maxALLEGROSQLLength := s.ssMap.maxALLEGROSQLLength() 727 c.Assert(maxALLEGROSQLLength, Equals, int(config.GetGlobalConfig().StmtSummary.MaxALLEGROSQLLength)) 728 729 // Create a long ALLEGROALLEGROSQL 730 length := maxALLEGROSQLLength * 10 731 str := strings.Repeat("a", length) 732 733 stmtInterDircInfo1 := generateAnyInterDircInfo() 734 stmtInterDircInfo1.OriginalALLEGROSQL = str 735 stmtInterDircInfo1.NormalizedALLEGROSQL = str 736 s.ssMap.AddStatement(stmtInterDircInfo1) 737 738 key := &stmtSummaryByDigestKey{ 739 schemaName: stmtInterDircInfo1.SchemaName, 740 digest: stmtInterDircInfo1.Digest, 741 planDigest: stmtInterDircInfo1.CausetDigest, 742 prevDigest: stmtInterDircInfo1.PrevALLEGROSQLDigest, 743 } 744 value, ok := s.ssMap.summaryMap.Get(key) 745 c.Assert(ok, IsTrue) 746 747 expectedALLEGROSQL := fmt.Sprintf("%s(len:%d)", strings.Repeat("a", maxALLEGROSQLLength), length) 748 summary := value.(*stmtSummaryByDigest) 749 c.Assert(summary.normalizedALLEGROSQL, Equals, expectedALLEGROSQL) 750 ssElement := summary.history.Back().Value.(*stmtSummaryByDigestElement) 751 c.Assert(ssElement.sampleALLEGROSQL, Equals, expectedALLEGROSQL) 752 753 c.Assert(s.ssMap.SetMaxALLEGROSQLLength("100", false), IsNil) 754 c.Assert(s.ssMap.maxALLEGROSQLLength(), Equals, 100) 755 c.Assert(s.ssMap.SetMaxALLEGROSQLLength("10", true), IsNil) 756 c.Assert(s.ssMap.maxALLEGROSQLLength(), Equals, 10) 757 c.Assert(s.ssMap.SetMaxALLEGROSQLLength("", true), IsNil) 758 c.Assert(s.ssMap.maxALLEGROSQLLength(), Equals, 100) 759 } 760 761 // Test AddStatement and SetMaxStmtCount parallel. 762 func (s *testStmtSummarySuite) TestSetMaxStmtCountParallel(c *C) { 763 s.ssMap.Clear() 764 now := time.Now().Unix() 765 // to disable expiration 766 s.ssMap.beginTimeForCurInterval = now + 60 767 768 threads := 8 769 loops := 20 770 wg := sync.WaitGroup{} 771 wg.Add(threads + 1) 772 773 addStmtFunc := func() { 774 defer wg.Done() 775 stmtInterDircInfo1 := generateAnyInterDircInfo() 776 777 // Add 32 times with different digest. 778 for i := 0; i < loops; i++ { 779 stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i) 780 s.ssMap.AddStatement(stmtInterDircInfo1) 781 } 782 } 783 for i := 0; i < threads; i++ { 784 go addStmtFunc() 785 } 786 787 defer c.Assert(s.ssMap.SetMaxStmtCount("", true), IsNil) 788 setStmtCountFunc := func() { 789 defer wg.Done() 790 // Turn down MaxStmtCount one by one. 791 for i := 10; i > 0; i-- { 792 c.Assert(s.ssMap.SetMaxStmtCount(strconv.Itoa(i), true), IsNil) 793 } 794 } 795 go setStmtCountFunc() 796 797 wg.Wait() 798 799 datums := s.ssMap.ToCurrentCauset(nil, true) 800 c.Assert(len(datums), Equals, 1) 801 } 802 803 // Test setting EnableStmtSummary to 0. 804 func (s *testStmtSummarySuite) TestDisableStmtSummary(c *C) { 805 s.ssMap.Clear() 806 now := time.Now().Unix() 807 808 // Set false in global scope, it should work. 809 s.ssMap.SetEnabled("0", false) 810 s.ssMap.beginTimeForCurInterval = now + 60 811 812 stmtInterDircInfo1 := generateAnyInterDircInfo() 813 s.ssMap.AddStatement(stmtInterDircInfo1) 814 datums := s.ssMap.ToCurrentCauset(nil, true) 815 c.Assert(len(datums), Equals, 0) 816 817 // Set true in stochastik scope, it will overwrite global scope. 818 s.ssMap.SetEnabled("1", true) 819 820 s.ssMap.AddStatement(stmtInterDircInfo1) 821 datums = s.ssMap.ToCurrentCauset(nil, true) 822 c.Assert(len(datums), Equals, 1) 823 824 // Set false in global scope, it shouldn't work. 825 s.ssMap.SetEnabled("0", false) 826 s.ssMap.beginTimeForCurInterval = now + 60 827 828 stmtInterDircInfo2 := stmtInterDircInfo1 829 stmtInterDircInfo2.OriginalALLEGROSQL = "original_sql2" 830 stmtInterDircInfo2.NormalizedALLEGROSQL = "normalized_sql2" 831 stmtInterDircInfo2.Digest = "digest2" 832 s.ssMap.AddStatement(stmtInterDircInfo2) 833 datums = s.ssMap.ToCurrentCauset(nil, true) 834 c.Assert(len(datums), Equals, 2) 835 836 // Unset in stochastik scope. 837 s.ssMap.SetEnabled("", true) 838 s.ssMap.beginTimeForCurInterval = now + 60 839 s.ssMap.AddStatement(stmtInterDircInfo2) 840 datums = s.ssMap.ToCurrentCauset(nil, true) 841 c.Assert(len(datums), Equals, 0) 842 843 // Unset in global scope. 844 s.ssMap.SetEnabled("", false) 845 s.ssMap.beginTimeForCurInterval = now + 60 846 s.ssMap.AddStatement(stmtInterDircInfo1) 847 datums = s.ssMap.ToCurrentCauset(nil, true) 848 c.Assert(len(datums), Equals, 1) 849 850 // Set back. 851 s.ssMap.SetEnabled("1", false) 852 } 853 854 // Test disable and enable memex summary concurrently with adding memexs. 855 func (s *testStmtSummarySuite) TestEnableSummaryParallel(c *C) { 856 s.ssMap.Clear() 857 858 threads := 8 859 loops := 32 860 wg := sync.WaitGroup{} 861 wg.Add(threads) 862 863 addStmtFunc := func() { 864 defer wg.Done() 865 stmtInterDircInfo1 := generateAnyInterDircInfo() 866 867 // Add 32 times with same digest. 868 for i := 0; i < loops; i++ { 869 // Sometimes enable it and sometimes disable it. 870 s.ssMap.SetEnabled(fmt.Sprintf("%d", i%2), false) 871 s.ssMap.AddStatement(stmtInterDircInfo1) 872 // Try to read it. 873 s.ssMap.ToHistoryCauset(nil, true) 874 } 875 s.ssMap.SetEnabled("1", false) 876 } 877 878 for i := 0; i < threads; i++ { 879 go addStmtFunc() 880 } 881 // Ensure that there's no deadlocks. 882 wg.Wait() 883 884 // Ensure that it's enabled at last. 885 c.Assert(s.ssMap.Enabled(), IsTrue) 886 } 887 888 // Test GetMoreThanOnceSelect. 889 func (s *testStmtSummarySuite) TestGetMoreThanOnceSelect(c *C) { 890 s.ssMap.Clear() 891 892 stmtInterDircInfo1 := generateAnyInterDircInfo() 893 stmtInterDircInfo1.OriginalALLEGROSQL = "insert 1" 894 stmtInterDircInfo1.NormalizedALLEGROSQL = "insert ?" 895 stmtInterDircInfo1.StmtCtx.StmtType = "Insert" 896 s.ssMap.AddStatement(stmtInterDircInfo1) 897 schemas, sqls := s.ssMap.GetMoreThanOnceSelect() 898 c.Assert(len(schemas), Equals, 0) 899 c.Assert(len(sqls), Equals, 0) 900 901 stmtInterDircInfo1.NormalizedALLEGROSQL = "select ?" 902 stmtInterDircInfo1.Digest = "digest1" 903 stmtInterDircInfo1.StmtCtx.StmtType = "Select" 904 s.ssMap.AddStatement(stmtInterDircInfo1) 905 schemas, sqls = s.ssMap.GetMoreThanOnceSelect() 906 c.Assert(len(schemas), Equals, 0) 907 c.Assert(len(sqls), Equals, 0) 908 909 s.ssMap.AddStatement(stmtInterDircInfo1) 910 schemas, sqls = s.ssMap.GetMoreThanOnceSelect() 911 c.Assert(len(schemas), Equals, 1) 912 c.Assert(len(sqls), Equals, 1) 913 } 914 915 // Test `formatBackoffTypes`. 916 func (s *testStmtSummarySuite) TestFormatBackoffTypes(c *C) { 917 backoffMap := make(map[fmt.Stringer]int) 918 c.Assert(formatBackoffTypes(backoffMap), IsNil) 919 920 backoffMap[einsteindb.BoFIDelRPC] = 1 921 c.Assert(formatBackoffTypes(backoffMap), Equals, "FIDelRPC:1") 922 923 backoffMap[einsteindb.BoTxnLock] = 2 924 c.Assert(formatBackoffTypes(backoffMap), Equals, "txnLock:2,FIDelRPC:1") 925 } 926 927 // Test refreshing current memex summary periodically. 928 func (s *testStmtSummarySuite) TestRefreshCurrentSummary(c *C) { 929 s.ssMap.Clear() 930 now := time.Now().Unix() 931 932 s.ssMap.beginTimeForCurInterval = now + 10 933 stmtInterDircInfo1 := generateAnyInterDircInfo() 934 key := &stmtSummaryByDigestKey{ 935 schemaName: stmtInterDircInfo1.SchemaName, 936 digest: stmtInterDircInfo1.Digest, 937 planDigest: stmtInterDircInfo1.CausetDigest, 938 } 939 s.ssMap.AddStatement(stmtInterDircInfo1) 940 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 941 value, ok := s.ssMap.summaryMap.Get(key) 942 c.Assert(ok, IsTrue) 943 ssElement := value.(*stmtSummaryByDigest).history.Back().Value.(*stmtSummaryByDigestElement) 944 c.Assert(ssElement.beginTime, Equals, s.ssMap.beginTimeForCurInterval) 945 c.Assert(ssElement.execCount, Equals, int64(1)) 946 947 s.ssMap.beginTimeForCurInterval = now - 1900 948 ssElement.beginTime = now - 1900 949 s.ssMap.AddStatement(stmtInterDircInfo1) 950 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 951 value, ok = s.ssMap.summaryMap.Get(key) 952 c.Assert(ok, IsTrue) 953 c.Assert(value.(*stmtSummaryByDigest).history.Len(), Equals, 2) 954 ssElement = value.(*stmtSummaryByDigest).history.Back().Value.(*stmtSummaryByDigestElement) 955 c.Assert(ssElement.beginTime, Greater, now-1900) 956 c.Assert(ssElement.execCount, Equals, int64(1)) 957 958 s.ssMap.SetRefreshInterval("10", false) 959 s.ssMap.beginTimeForCurInterval = now - 20 960 ssElement.beginTime = now - 20 961 s.ssMap.AddStatement(stmtInterDircInfo1) 962 c.Assert(value.(*stmtSummaryByDigest).history.Len(), Equals, 3) 963 } 964 965 // Test expiring memex summary to history. 966 func (s *testStmtSummarySuite) TestSummaryHistory(c *C) { 967 s.ssMap.Clear() 968 now := time.Now().Unix() 969 s.ssMap.SetRefreshInterval("10", false) 970 s.ssMap.SetHistorySize("10", false) 971 defer s.ssMap.SetRefreshInterval("1800", false) 972 defer s.ssMap.SetHistorySize("24", false) 973 974 stmtInterDircInfo1 := generateAnyInterDircInfo() 975 key := &stmtSummaryByDigestKey{ 976 schemaName: stmtInterDircInfo1.SchemaName, 977 digest: stmtInterDircInfo1.Digest, 978 planDigest: stmtInterDircInfo1.CausetDigest, 979 } 980 for i := 0; i < 11; i++ { 981 s.ssMap.beginTimeForCurInterval = now + int64(i+1)*10 982 s.ssMap.AddStatement(stmtInterDircInfo1) 983 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 984 value, ok := s.ssMap.summaryMap.Get(key) 985 c.Assert(ok, IsTrue) 986 ssbd := value.(*stmtSummaryByDigest) 987 if i < 10 { 988 c.Assert(ssbd.history.Len(), Equals, i+1) 989 ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement) 990 c.Assert(ssElement.beginTime, Equals, s.ssMap.beginTimeForCurInterval) 991 c.Assert(ssElement.execCount, Equals, int64(1)) 992 } else { 993 c.Assert(ssbd.history.Len(), Equals, 10) 994 ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement) 995 c.Assert(ssElement.beginTime, Equals, s.ssMap.beginTimeForCurInterval) 996 ssElement = ssbd.history.Front().Value.(*stmtSummaryByDigestElement) 997 c.Assert(ssElement.beginTime, Equals, now+20) 998 } 999 } 1000 causet := s.ssMap.ToHistoryCauset(nil, true) 1001 c.Assert(len(causet), Equals, 10) 1002 1003 s.ssMap.SetHistorySize("5", false) 1004 causet = s.ssMap.ToHistoryCauset(nil, true) 1005 c.Assert(len(causet), Equals, 5) 1006 } 1007 1008 // Test summary when PrevALLEGROSQL is not empty. 1009 func (s *testStmtSummarySuite) TestPrevALLEGROSQL(c *C) { 1010 s.ssMap.Clear() 1011 now := time.Now().Unix() 1012 // to disable expiration 1013 s.ssMap.beginTimeForCurInterval = now + 60 1014 1015 stmtInterDircInfo1 := generateAnyInterDircInfo() 1016 stmtInterDircInfo1.PrevALLEGROSQL = "prevALLEGROSQL" 1017 stmtInterDircInfo1.PrevALLEGROSQLDigest = "prevALLEGROSQLDigest" 1018 s.ssMap.AddStatement(stmtInterDircInfo1) 1019 key := &stmtSummaryByDigestKey{ 1020 schemaName: stmtInterDircInfo1.SchemaName, 1021 digest: stmtInterDircInfo1.Digest, 1022 planDigest: stmtInterDircInfo1.CausetDigest, 1023 prevDigest: stmtInterDircInfo1.PrevALLEGROSQLDigest, 1024 } 1025 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 1026 _, ok := s.ssMap.summaryMap.Get(key) 1027 c.Assert(ok, IsTrue) 1028 1029 // same prevALLEGROSQL 1030 s.ssMap.AddStatement(stmtInterDircInfo1) 1031 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 1032 1033 // different prevALLEGROSQL 1034 stmtInterDircInfo2 := stmtInterDircInfo1 1035 stmtInterDircInfo2.PrevALLEGROSQL = "prevALLEGROSQL1" 1036 stmtInterDircInfo2.PrevALLEGROSQLDigest = "prevALLEGROSQLDigest1" 1037 key.prevDigest = stmtInterDircInfo2.PrevALLEGROSQLDigest 1038 s.ssMap.AddStatement(stmtInterDircInfo2) 1039 c.Assert(s.ssMap.summaryMap.Size(), Equals, 2) 1040 _, ok = s.ssMap.summaryMap.Get(key) 1041 c.Assert(ok, IsTrue) 1042 } 1043 1044 func (s *testStmtSummarySuite) TestEndTime(c *C) { 1045 s.ssMap.Clear() 1046 now := time.Now().Unix() 1047 s.ssMap.beginTimeForCurInterval = now - 100 1048 1049 stmtInterDircInfo1 := generateAnyInterDircInfo() 1050 s.ssMap.AddStatement(stmtInterDircInfo1) 1051 key := &stmtSummaryByDigestKey{ 1052 schemaName: stmtInterDircInfo1.SchemaName, 1053 digest: stmtInterDircInfo1.Digest, 1054 planDigest: stmtInterDircInfo1.CausetDigest, 1055 } 1056 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 1057 value, ok := s.ssMap.summaryMap.Get(key) 1058 c.Assert(ok, IsTrue) 1059 ssbd := value.(*stmtSummaryByDigest) 1060 ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement) 1061 c.Assert(ssElement.beginTime, Equals, now-100) 1062 c.Assert(ssElement.endTime, Equals, now+1700) 1063 1064 s.ssMap.SetRefreshInterval("3600", false) 1065 defer s.ssMap.SetRefreshInterval("1800", false) 1066 s.ssMap.AddStatement(stmtInterDircInfo1) 1067 c.Assert(ssbd.history.Len(), Equals, 1) 1068 ssElement = ssbd.history.Back().Value.(*stmtSummaryByDigestElement) 1069 c.Assert(ssElement.beginTime, Equals, now-100) 1070 c.Assert(ssElement.endTime, Equals, now+3500) 1071 1072 s.ssMap.SetRefreshInterval("60", false) 1073 s.ssMap.AddStatement(stmtInterDircInfo1) 1074 c.Assert(ssbd.history.Len(), Equals, 2) 1075 now2 := time.Now().Unix() 1076 ssElement = ssbd.history.Front().Value.(*stmtSummaryByDigestElement) 1077 c.Assert(ssElement.beginTime, Equals, now-100) 1078 c.Assert(ssElement.endTime, GreaterEqual, now) 1079 c.Assert(ssElement.endTime, LessEqual, now2) 1080 ssElement = ssbd.history.Back().Value.(*stmtSummaryByDigestElement) 1081 c.Assert(ssElement.beginTime, GreaterEqual, now-60) 1082 c.Assert(ssElement.beginTime, LessEqual, now2) 1083 c.Assert(ssElement.endTime-ssElement.beginTime, Equals, int64(60)) 1084 } 1085 1086 func (s *testStmtSummarySuite) TestPointGet(c *C) { 1087 s.ssMap.Clear() 1088 now := time.Now().Unix() 1089 s.ssMap.beginTimeForCurInterval = now - 100 1090 1091 stmtInterDircInfo1 := generateAnyInterDircInfo() 1092 stmtInterDircInfo1.CausetDigest = "" 1093 stmtInterDircInfo1.CausetDigestGen = fakeCausetDigestGenerator 1094 s.ssMap.AddStatement(stmtInterDircInfo1) 1095 key := &stmtSummaryByDigestKey{ 1096 schemaName: stmtInterDircInfo1.SchemaName, 1097 digest: stmtInterDircInfo1.Digest, 1098 planDigest: "", 1099 } 1100 c.Assert(s.ssMap.summaryMap.Size(), Equals, 1) 1101 value, ok := s.ssMap.summaryMap.Get(key) 1102 c.Assert(ok, IsTrue) 1103 ssbd := value.(*stmtSummaryByDigest) 1104 ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement) 1105 c.Assert(ssElement.execCount, Equals, int64(1)) 1106 1107 s.ssMap.AddStatement(stmtInterDircInfo1) 1108 c.Assert(ssElement.execCount, Equals, int64(2)) 1109 } 1110 1111 func (s *testStmtSummarySuite) TestAccessPrivilege(c *C) { 1112 s.ssMap.Clear() 1113 1114 loops := 32 1115 stmtInterDircInfo1 := generateAnyInterDircInfo() 1116 1117 for i := 0; i < loops; i++ { 1118 stmtInterDircInfo1.Digest = fmt.Sprintf("digest%d", i) 1119 s.ssMap.AddStatement(stmtInterDircInfo1) 1120 } 1121 1122 user := &auth.UserIdentity{Username: "user"} 1123 badUser := &auth.UserIdentity{Username: "bad_user"} 1124 1125 datums := s.ssMap.ToCurrentCauset(user, false) 1126 c.Assert(len(datums), Equals, loops) 1127 datums = s.ssMap.ToCurrentCauset(badUser, false) 1128 c.Assert(len(datums), Equals, 0) 1129 datums = s.ssMap.ToCurrentCauset(badUser, true) 1130 c.Assert(len(datums), Equals, loops) 1131 1132 datums = s.ssMap.ToHistoryCauset(user, false) 1133 c.Assert(len(datums), Equals, loops) 1134 datums = s.ssMap.ToHistoryCauset(badUser, false) 1135 c.Assert(len(datums), Equals, 0) 1136 datums = s.ssMap.ToHistoryCauset(badUser, true) 1137 c.Assert(len(datums), Equals, loops) 1138 }