1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 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 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { KeyPathStruct } from '../../bean/KeyPathStruct'; 17import { CpuStruct } from '../ui-worker/cpu/ProcedureWorkerCPU'; 18import { query } from '../SqlLite'; 19import { CpuUsage, Freq } from '../../bean/CpuUsage'; 20import { Counter } from '../../bean/BoxSelection'; 21import { CpuFreqStruct } from '../ui-worker/ProcedureWorkerFreq'; 22import { CpuFreqLimitsStruct } from '../ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; 23import { CpuFreqRowLimit } from '../../component/chart/SpFreqChart'; 24import { Utils } from '../../component/trace/base/Utils'; 25 26export const queryCpuKeyPathData = (threads: Array<KeyPathStruct>): Promise<Array<CpuStruct>> => { 27 const sqlArray: Array<string> = []; 28 sqlArray.push(' 1 = 0'); 29 for (const thread of threads) { 30 sqlArray.push(` or (tid = ${thread.tid} and ts in (${thread.tsArray}))`); 31 } 32 let sql = sqlArray.join(' '); 33 return query( 34 'queryCpuKeyPathData', 35 `SELECT B.pid as processId, 36 B.cpu, 37 B.tid, 38 B.itid as id, 39 B.dur AS dur, 40 B.ts - T.start_ts AS startTime, 41 B.arg_setid as argSetID, 42 1 as isKeyPath 43 from thread_state AS B 44 left join trace_range as T 45 where ${sql}` 46 ); 47}; 48 49export const getTabCpuUsage = (cpus: Array<number>, leftNs: number, rightNs: number, 50 traceId?: string): Promise<Array<CpuUsage>> => 51 query<CpuUsage>( 52 'getTabCpuUsage', 53 ` 54 select 55 cpu, 56 sum(case 57 when (A.ts - B.start_ts) < $leftNS 58 then (A.ts - B.start_ts + A.dur - $leftNS) 59 when (A.ts - B.start_ts) >= $leftNS 60 and (A.ts - B.start_ts + A.dur) <= $rightNS 61 then A.dur 62 when (A.ts - B.start_ts + A.dur) > $rightNS 63 then ($rightNS - (A.ts - B.start_ts)) end) / cast($rightNS - $leftNS as float) as usage 64 from 65 thread_state A, 66 trace_range B 67 where 68 (A.ts - B.start_ts) > 0 and A.dur > 0 69 and 70 cpu in (${cpus.join(',')}) 71 and 72 (A.ts - B.start_ts + A.dur) > $leftNS 73 and 74 (A.ts - B.start_ts) < $rightNS 75 group by 76 cpu`, 77 { $leftNS: leftNs, $rightNS: rightNs }, 78 { traceId: traceId } 79 ); 80 81export const getTabCpuFreq = (cpus: Array<number>, leftNs: number, rightNs: number, 82 traceId?: string): Promise<Array<Freq>> => 83 query<Freq>( 84 'getTabCpuFreq', 85 ` 86 select 87 cpu, 88 value, 89 (ts - tr.start_ts) as startNs 90 from 91 measure m, 92 trace_range tr 93 inner join 94 cpu_measure_filter t 95 on 96 m.filter_id = t.id 97 where 98 (name = 'cpufreq' or name='cpu_frequency') 99 and 100 cpu in (${cpus.join(',')}) 101 and 102 startNs > 0 103 and 104 startNs < $rightNS 105 --order by startNs 106 `, 107 { $leftNS: leftNs, $rightNS: rightNs }, 108 { traceId: traceId } 109 ); 110 111export const getTabCounters = ( 112 processFilterIds: Array<number>, 113 virtualFilterIds: Array<number>, 114 startTime: number 115): //@ts-ignore 116Promise<unknown> => { 117 let processSql = `select 118 t1.filter_id as trackId, 119 t2.name, 120 value, 121 t1.ts - t3.start_ts as startTime 122 from 123 process_measure t1 124 left join 125 process_measure_filter t2 126 on 127 t1.filter_id = t2.id 128 left join 129 trace_range t3 130 where 131 filter_id in (${processFilterIds.join(',')}) 132 and 133 startTime <= ${startTime}`; 134 let virtualSql = `select 135 t1.filter_id as trackId, 136 t2.name, 137 value, 138 t1.ts - t3.start_ts as startTime 139 from 140 sys_mem_measure t1 141 left join 142 sys_event_filter t2 143 on 144 t1.filter_id = t2.id 145 left join 146 trace_range t3 147 where 148 filter_id in (${virtualFilterIds.join(',')}) 149 and 150 startTime <= ${startTime}`; 151 let sql = ''; 152 if (processFilterIds.length > 0 && virtualFilterIds.length > 0) { 153 sql = `${processSql} union ${virtualSql}`; 154 } else { 155 if (processFilterIds.length > 0) { 156 sql = processSql; 157 } else { 158 sql = virtualSql; 159 } 160 } 161 return query<Counter>('getTabCounters', sql, {}); 162}; 163export const getTabCpuByProcess = ( 164 cpus: Array<number>, 165 leftNS: number, 166 rightNS: number, 167 traceId?: string 168): //@ts-ignore 169Promise<unknown[]> => //@ts-ignore 170 query<unknown>( 171 'getTabCpuByProcess', 172 ` 173 select 174 B.pid as pid, 175 sum(iif(B.dur = -1 or B.dur is null, 0, B.dur)) as wallDuration, 176 avg(iif(B.dur = -1 or B.dur is null, 0, B.dur)) as avgDuration, 177 count(B.tid) as occurrences 178 from 179 thread_state AS B 180 left join 181 trace_range AS TR 182 where 183 B.cpu in (${cpus.join(',')}) 184 and 185 not ((B.ts - TR.start_ts + iif(B.dur = -1 or B.dur is null, 0, B.dur) < $leftNS) 186 or (B.ts - TR.start_ts > $rightNS )) 187 group by 188 B.pid 189 order by 190 wallDuration desc;`, 191 { $rightNS: rightNS, $leftNS: leftNS }, 192 { traceId: traceId } 193 ); 194 195export const getTabCpuByThread = (cpus: Array<number>, leftNS: number, rightNS: number, 196 traceId?: string): Promise<unknown[]> => 197 query<unknown>( 198 'getTabCpuByThread', 199 ` 200 select 201 TS.pid as pid, 202 TS.tid as tid, 203 TS.cpu, 204 sum( min(${rightNS},(TS.ts - TR.start_ts + iif(TS.dur = -1 or TS.dur is null, 0, TS.dur))) - 205 max(${leftNS},TS.ts - TR.start_ts)) wallDuration, 206 count(TS.tid) as occurrences 207 from 208 thread_state AS TS 209 left join 210 trace_range AS TR 211 where 212 TS.cpu in (${cpus.join(',')}) 213 and 214 not ((TS.ts - TR.start_ts + iif(TS.dur = -1 or TS.dur is null, 0, TS.dur) < $leftNS) 215 or (TS.ts - TR.start_ts > $rightNS)) 216 group by 217 TS.cpu, 218 TS.pid, 219 TS.tid 220 order by 221 wallDuration desc;`, 222 { $rightNS: rightNS, $leftNS: leftNS }, 223 { traceId: traceId } 224 ); 225 226export const queryCpuData = (cpu: number, startNS: number, endNS: number): Promise<Array<CpuStruct>> => 227 query( 228 'queryCpuData', 229 ` 230 SELECT 231 B.pid as processId, 232 B.cpu, 233 B.tid, 234 B.itid as id, 235 B.dur, 236 B.ts - TR.start_ts AS startTime, 237 B.arg_setid as argSetID 238from thread_state AS B 239 left join trace_range AS TR 240where B.itid is not null 241 and 242 B.cpu = $cpu 243 and 244 startTime between $startNS and $endNS;`, 245 { 246 $cpu: cpu, 247 $startNS: startNS, 248 $endNS: endNS, 249 } 250 ); 251 252export const queryCpuFreq = (traceId?: string): Promise<Array<{ cpu: number; filterId: number }>> => 253 query( 254 'queryCpuFreq', 255 ` 256 select 257 cpu,id as filterId 258 from 259 cpu_measure_filter 260 where 261 (name='cpufreq' or name='cpu_frequency') 262 order by cpu; 263 `, {}, { traceId: traceId } 264 ); 265 266export const queryCpuFreqData = (cpu: number): Promise<Array<CpuFreqStruct>> => 267 query<CpuFreqStruct>( 268 'queryCpuFreqData', 269 ` 270 select 271 cpu, 272 value, 273 ifnull(dur,tb.end_ts - c.ts) dur, 274 ts-tb.start_ts as startNS 275 from 276 measure c, 277 trace_range tb 278 inner join 279 cpu_measure_filter t 280 on 281 c.filter_id = t.id 282 where 283 (name = 'cpufreq' or name='cpu_frequency') 284 and 285 cpu= $cpu 286 --order by ts; 287 `, 288 { $cpu: cpu } 289 ); 290 291export const queryCpuMax = (traceId?: string): //@ts-ignore 292Promise<Array<unknown>> => 293 query( 294 'queryCpuMax', 295 ` 296 select 297 cpu 298 from 299 sched_slice 300 order by 301 cpu 302 desc limit 1;`, 303 {}, 304 { traceId: traceId } 305 ); 306 307export const queryCpuDataCount = (): Promise<unknown[]> => 308 query('queryCpuDataCount', 309 'select count(1) as count,cpu from thread_state where cpu not null group by cpu'); 310 311export const queryCpuCount = (traceId?: string): //@ts-ignore 312Promise<Array<unknown>> => 313 query( 314 'queryCpuCount', 315 ` 316 select max(cpuCount) cpuCount from 317(select ifnull((max(cpu) + 1),0) cpuCount from cpu_measure_filter where name in ('cpu_frequency','cpu_idle') 318 union all 319 select ifnull((max(callid)+1),0) cpuCount from irq 320) A;`, 321 {}, 322 { traceId: traceId } 323 ); 324 325export const queryCpuSchedSlice = async (traceId?: string): Promise<Array<unknown>> => { 326 let cpuSchedSliceBuffer = await query( 327 'queryCpuSchedSlice', 328 `select 329 (ts - start_ts) as ts, 330 itid, 331 end_state as endState, 332 priority 333 from 334 sched_slice, 335 trace_range;`, 336 {}, 337 { traceId: traceId, action: 'exec-buf' } 338 ); 339 // @ts-ignore 340 return Utils.convertJSON(cpuSchedSliceBuffer); 341}; 342 343export const queryCpuStateFilter = (traceId?: string): 344Promise<Array<{ cpu: number; filterId: number }>> => 345 query( 346 'queryCpuStateFilter', 347 `select cpu,id as filterId 348 from cpu_measure_filter 349 where name = 'cpu_idle' order by cpu;`, 350 {}, 351 { traceId: traceId } 352 ); 353 354export const queryCpuState = ( 355 cpuFilterId: number 356): //@ts-ignore 357Promise<Array<unknown>> => 358 query( 359 'queryCpuState', 360 ` 361 select (A.ts - B.start_ts) as startTs,ifnull(dur,B.end_ts - A.ts) dur, 362 value 363 from measure A,trace_range B 364 where filter_id = $filterId;`, 365 { $filterId: cpuFilterId } 366 ); 367 368export const queryCpuMaxFreq = (traceId?: string): 369Promise<Array<{ 370 maxFreq: number 371}>> => 372 query( 373 'queryCpuMaxFreq', 374 ` 375 select 376 max(value) as maxFreq 377 from 378 measure c 379 inner join 380 cpu_measure_filter t 381 on 382 c.filter_id = t.id 383 where 384 (name = 'cpufreq' or name='cpu_frequency');`, {}, { traceId: traceId } 385 ); 386 387export const queryTraceCpu = (): Promise< 388 Array<{ 389 tid: string; 390 pid: string; 391 cpu: string; 392 dur: string; 393 min_freq: string; 394 max_freq: string; 395 avg_frequency: string; 396 }> 397> => 398 query( 399 'queryTraceCpu', 400 `SELECT 401 itid AS tid, 402 ipid AS pid, 403 group_concat(cpu, ',') AS cpu, 404 group_concat(dur, ',') AS dur, 405 group_concat(min_freq, ',') AS min_freq, 406 group_concat(max_freq, ',') AS max_freq, 407 group_concat(avg_frequency, ',') AS avg_frequency 408 FROM 409 (SELECT 410 itid, 411 ipid, 412 cpu, 413 CAST (SUM(dur) AS INT) AS dur, 414 CAST (MIN(freq) AS INT) AS min_freq, 415 CAST (MAX(freq) AS INT) AS max_freq, 416 CAST ( (SUM(dur * freq) / SUM(dur) ) AS INT) AS avg_frequency 417 from 418 result 419 group by 420 itid, cpu 421 ) 422 GROUP BY 423 ipid, itid 424 ORDER BY 425 ipid 426 ` 427 ); 428 429export const queryTraceCpuTop = (): Promise< 430 Array<{ 431 tid: string; 432 pid: string; 433 cpu: string; 434 duration: string; 435 min_freq: string; 436 max_freq: string; 437 avg_frequency: string; 438 sumNum: string; 439 }> 440> => 441 query( 442 'queryTraceCpuTop', 443 `SELECT 444 ipid AS pid, 445 itid AS tid, 446 group_concat(cpu, ',') AS cpu, 447 group_concat(dur, ',') AS dur, 448 group_concat(avg_frequency, ',') AS avg_frequency, 449 group_concat(min_freq, ',') AS min_freq, 450 group_concat(max_freq, ',') AS max_freq, 451 sum(dur * avg_frequency) AS sumNum 452 FROM 453 (SELECT 454 itid, 455 ipid, 456 cpu, 457 CAST (SUM(dur) AS INT) AS dur, 458 CAST (MIN(freq) AS INT) AS min_freq, 459 CAST (MAX(freq) AS INT) AS max_freq, 460 CAST ( (SUM(dur * freq) / SUM(dur) ) AS INT) AS avg_frequency 461 from result group by itid, cpu 462 ) 463 GROUP BY 464 ipid, itid 465 ORDER BY 466 sumNum 467 DESC 468 LIMIT 10; 469 ` 470 ); 471 472export const queryCpuFreqUsageData = ( 473 Ids: Array<number> 474): Promise< 475 Array<{ 476 startNS: number; 477 filter_id: number; 478 value: number; 479 dur: number; 480 }> 481> => 482 query( 483 'queryCpuFreqUsageData', 484 `select 485 value, 486 ifnull(dur,tb.end_ts - c.ts) dur, 487 ts-tb.start_ts as startNS, 488 filter_id 489 from 490 measure c, 491 trace_range tb 492 where 493 c.filter_id in (${Ids.join(',')}) 494 `, 495 {}, 496 { traceId: Utils.currentSelectTrace } 497 ); 498 499export const queryCpuFreqFilterId = (): Promise< 500 Array<{ 501 id: number; 502 cpu: number; 503 }> 504> => 505 query( 506 'queryCpuFreqFilterId', 507 ` 508 select 509 id, 510 cpu 511 from 512 cpu_measure_filter 513 where 514 name='cpufreq' 515 or 516 name='cpu_frequency' 517 `, 518 {}, 519 { traceId: Utils.currentSelectTrace } 520 ); 521 522export const searchCpuData = ( 523 keyword: string 524): //@ts-ignore 525Promise<Array<unknown>> => { 526 let id = parseInt(keyword); 527 let sql = ` 528 select B.pid as processId, 529 B.cpu, 530 B.tid, 531 'cpu' as type, 532 B.itid as id, 533 B.dur as dur, 534 B.ts - TR.start_ts as startTime, 535 B.arg_setid as argSetID 536from thread_state AS B, trace_range TR 537 left join process p on B.pid = p.pid 538 left join thread t on B.itid = t.itid 539where B.cpu not null and B.ts between TR.start_ts and TR.end_ts 540 and ( 541 t.name like '%${keyword}%' 542 or B.tid = ${Number.isNaN(id) ? -1 : id} 543 or B.pid = ${Number.isNaN(id) ? -1 : id} 544 or p.name like '%${keyword}%' 545 ) 546order by startTime;`; 547 return query('searchCpuData', sql, {}); 548}; 549 550export const getTabPaneCounterSampleData = ( 551 leftNs: number, 552 rightNs: number, 553 cpuStateFilterIds: Array<number> 554): //@ts-ignore 555Promise<Array<unknown>> => { 556 let str = ''; 557 if (cpuStateFilterIds.length > 0) { 558 str = ` and filter_id in (${cpuStateFilterIds.join(',')})`; 559 } 560 return query( 561 'getTabPaneCounterSampleData', 562 ` 563 select value, filter_id as filterId, ts, f.cpu 564 from measure left join cpu_measure_filter as f on f.id=filter_id 565 where 566 ts <= $rightNs${str} order by ts asc; 567`, 568 { $leftNs: leftNs, $rightNs: rightNs }, {traceId: Utils.currentSelectTrace} 569 ); 570}; 571export const queryJsCpuProfilerConfig = (): //@ts-ignore 572Promise<Array<unknown>> => 573 query('queryJsCpuProfilerConfig', 574 'SELECT pid, type, enable_cpu_Profiler as enableCpuProfiler FROM js_config'); 575 576export const queryJsCpuProfilerData = (): //@ts-ignore 577Promise<Array<unknown>> => query('queryJsCpuProfilerData', 578 'SELECT 1 WHERE EXISTS(select 1 from js_cpu_profiler_node)'); 579 580export const querySystemCallsTop = (): Promise< 581 Array<{ 582 tid: string; 583 pid: string; 584 funName: string; 585 frequency: string; 586 minDur: string; 587 maxDur: string; 588 avgDur: string; 589 }> 590> => 591 query( 592 'querySystemCallsTop', 593 `SELECT 594 cpu.tid AS tid, 595 cpu.pid AS pid, 596 callstack.name AS funName, 597 count(callstack.name) AS frequency, 598 min(callstack.dur) AS minDur, 599 max(callstack.dur) AS maxDur, 600 round(avg(callstack.dur)) AS avgDur 601 FROM 602 callstack 603 INNER JOIN 604 (SELECT 605 itid AS tid, 606 ipid AS pid, 607 group_concat(cpu, ',') AS cpu, 608 group_concat(dur, ',') AS dur, 609 group_concat(min_freq, ',') AS min_freq, 610 group_concat(max_freq, ',') AS max_freq, 611 group_concat(avg_frequency, ',') AS avg_frequency, 612 sum(dur * avg_frequency) AS sumNum 613 FROM 614 (SELECT 615 itid, 616 ipid, 617 cpu, 618 CAST (SUM(dur) AS INT) AS dur, 619 CAST (MIN(freq) AS INT) AS min_freq, 620 CAST (MAX(freq) AS INT) AS max_freq, 621 CAST ( (SUM(dur * freq) / SUM(dur) ) AS INT) AS avg_frequency 622 FROM 623 result 624 GROUP BY 625 itid, cpu 626 ) 627 GROUP BY 628 ipid, itid 629 ORDER BY 630 sumNum 631 DESC 632 LIMIT 10 633 ) AS cpu 634 ON 635 callstack.callid = cpu.tid 636 GROUP BY 637 callstack.name 638 ORDER BY 639 frequency 640 DESC 641 LIMIT 10` 642 ); 643 644export const queryWakeupListPriority = ( 645 itid: number[], 646 ts: number[], 647 cpus: number[] 648): //@ts-ignore 649Promise<Array<unknown>> => 650 query( 651 'queryWakeupListPriority', 652 ` 653 select itid, priority, (ts - start_ts) as ts, dur, cpu 654 from sched_slice,trace_range where cpu in (${cpus.join(',')}) 655 and itid in (${itid.join(',')}) 656 and ts - start_ts in (${ts.join(',')}) 657 `, 658 {}, 659 { traceId: Utils.currentSelectTrace } 660 ); 661 662export const getCpuLimitFreqBoxSelect = ( 663 arr: Array<{ 664 maxFilterId: string; 665 minFilterId: string; 666 cpu: string; 667 }>, 668 rightNS: number 669): //@ts-ignore 670Promise<Array<unknown>> => { 671 let ids = []; 672 let condition = `(case`; 673 for (let item of arr) { 674 condition = `${condition} when filter_id in (${item.maxFilterId}, ${item.minFilterId}) then ${item.cpu}`; 675 ids.push(item.maxFilterId, item.minFilterId); 676 } 677 condition = `${condition} else -1 end) as cpu`; 678 let sql = ` 679 select 680 ts - T.start_ts as startNs, 681 dur, 682 max(value) as max, 683 min(value) as min, 684 ${condition} 685 from measure,trace_range T 686 where filter_id in (${ids.join(',')}) 687 and ts - T.start_ts < ${rightNS} 688 group by ts 689 `; 690 return query('getCpuLimitFreqBoxSelect', sql, {}, {traceId: Utils.currentSelectTrace}); 691}; 692 693export const getCpuLimitFreq = (maxId: number, minId: number, cpu: number): 694 Promise<Array<CpuFreqLimitsStruct>> => 695 query( 696 'getCpuLimitFreq', 697 ` 698 select ts - T.start_ts as startNs, 699 dur, 700 max(value) as max, 701 min(value) as min, 702 $cpu as cpu 703 from measure,trace_range T where filter_id in ($maxId,$minId) group by ts 704`, 705 { $maxId: maxId, $minId: minId, $cpu: cpu } 706 ); 707 708export const getCpuLimitFreqId = (traceId?: string): Promise<Array<CpuFreqRowLimit>> => 709 query( 710 'getCpuMaxMinFreqId', 711 ` 712 select 713 cpu, 714 MAX(iif(name = 'cpu_frequency_limits_max',id,0)) as maxFilterId, 715 MAX(iif(name = 'cpu_frequency_limits_min',id,0)) as minFilterId 716 from cpu_measure_filter 717 where name in ('cpu_frequency_limits_max','cpu_frequency_limits_min') group by cpu 718`, 719 {}, 720 { traceId: traceId } 721 ); 722 723export const getCpuLimitFreqMax = ( 724 filterIds: string, 725 traceId?: string 726): Promise<Array<{ maxValue: number; filterId: number }>> => { 727 return query( 728 'getCpuLimitFreqMax', 729 ` 730 select max(value) as maxValue,filter_id as filterId 731 from measure where filter_id in (${filterIds}) group by filter_id 732`, 733 {}, 734 { traceId: traceId } 735 ); 736}; 737