1// Copyright (c) 2021 Huawei Device Co., Ltd. 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14import { TraficEnum } from '../utils/QueryEnum'; 15 16export const chartHiperfThreadData10MSProtoSql = (args: any): string => { 17 return `select startNS as startNS, 18 max(event_count) eventCount, 19 sample_count as sampleCount, 20 event_type_id as eventTypeId, 21 callchain_id as callchainId, 22 (startNS / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px 23 from (SELECT sp.callchain_id, 24 (sp.timestamp_trace - ${args.recordStartNS}) / 10000000 * 10000000 startNS, 25 sum(event_count) event_count, 26 count(event_count) sample_count, 27 event_type_id 28 from perf_sample sp 29 where sp.thread_id = ${args.tid} 30 and sp.thread_id != 0 ${args.drawType >= 0 ? 'and event_type_id =' + args.drawType : ''} 31 group by startNS) 32 where startNS + 10000000 >= ${Math.floor(args.startNS)} 33 and startNS <= ${Math.floor(args.endNS)} 34 group by px;`; 35}; 36export const chartHiperfThreadDataProtoSql = (args: any): string => { 37 return `SELECT (sp.timestamp_trace - ${args.recordStartNS}) startNS, 38 event_count as eventCount, 39 1 as sampleCount, 40 event_type_id as eventTypeId, 41 sp.callchain_id as callchainId, 42 (sp.timestamp_trace - ${args.recordStartNS}) / (${Math.floor( 43 (args.endNS - args.startNS) / args.width 44 )}) AS px 45 from perf_sample sp 46 where sp.thread_id = ${args.tid} 47 and sp.thread_id != 0 ${args.drawType >= 0 ? 'and event_type_id =' + args.drawType : ''} 48 and startNS >= ${Math.floor(args.startNS)} 49 and startNS <= ${Math.floor(args.endNS)} 50 group by px;`; 51}; 52 53export function hiperfThreadDataReceiver(data: any, proc: Function): void { 54 let sql: string; 55 if (data.params.scale > 30_000_000) { 56 sql = chartHiperfThreadData10MSProtoSql(data.params); 57 } else { 58 sql = chartHiperfThreadDataProtoSql(data.params); 59 } 60 let res = proc(sql); 61 arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); 62} 63 64function arrayBufferHandler(data: any, res: any[], transfer: boolean): void { 65 let maxCpuCount = data.params.maxCpuCount; 66 let intervalPerf = data.params.intervalPerf; 67 let usage = data.params.drawType === -2; 68 let perfThread = new PerfThread(data, transfer, res.length); 69 let maxEventCount = Math.max( 70 ...res.map((it) => { 71 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.hiperfData); 72 return it.eventCount; 73 }) 74 ); 75 res.forEach((it, i) => { 76 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.hiperfData); 77 perfThread.startNS[i] = it.startNS || it.startNs; 78 perfThread.eventCount[i] = it.eventCount; 79 perfThread.sampleCount[i] = it.sampleCount; 80 perfThread.eventTypeId[i] = it.eventTypeId; 81 perfThread.callChainId[i] = it.callchainId; 82 if (usage) { 83 perfThread.height[i] = maxCpuCount === -1 84 ? Math.floor((it.sampleCount / (10 / intervalPerf)) * 40) 85 : Math.floor((it.sampleCount / (10 / intervalPerf) / maxCpuCount) * 40); 86 } else { 87 perfThread.height[i] = Math.floor((it.eventCount / maxEventCount) * 40); 88 } 89 }); 90 postPerfThreadMessage(data, transfer, perfThread, res.length); 91} 92function postPerfThreadMessage(data: any, transfer: boolean, perfThread: PerfThread, len: number) { 93 (self as unknown as Worker).postMessage( 94 { 95 id: data.id, 96 action: data.action, 97 results: transfer 98 ? { 99 startNS: perfThread.startNS.buffer, 100 eventCount: perfThread.eventCount.buffer, 101 sampleCount: perfThread.sampleCount.buffer, 102 eventTypeId: perfThread.eventTypeId.buffer, 103 callChainId: perfThread.callChainId.buffer, 104 height: perfThread.height.buffer, 105 } 106 : {}, 107 len: len, 108 transfer: transfer, 109 }, 110 transfer 111 ? [ 112 perfThread.startNS.buffer, 113 perfThread.eventCount.buffer, 114 perfThread.sampleCount.buffer, 115 perfThread.eventTypeId.buffer, 116 perfThread.callChainId.buffer, 117 perfThread.height.buffer, 118 ] 119 : [] 120 ); 121} 122class PerfThread { 123 startNS: Float64Array; 124 eventCount: Int32Array; 125 sampleCount: Int32Array; 126 eventTypeId: Int32Array; 127 callChainId: Int32Array; 128 height: Int32Array; 129 constructor(data: any, transfer: boolean, len: number) { 130 this.startNS = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.startNS); 131 this.eventCount = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.eventCount); 132 this.sampleCount = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.sampleCount); 133 this.eventTypeId = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.eventTypeId); 134 this.callChainId = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.callChainId); 135 this.height = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.height); 136 } 137} 138