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 { Args } from '../CommonArgs'; 15import { TraficEnum } from '../utils/QueryEnum'; 16 17export const chartHiperfThreadData10MSProtoSql = (args: Args): string => { 18 return `select startNS as startNS, 19 max(event_count) eventCount, 20 sample_count as sampleCount, 21 event_type_id as eventTypeId, 22 callchain_id as callchainId, 23 (startNS / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px 24 from (SELECT sp.callchain_id, 25 (sp.timestamp_trace - ${args.recordStartNS}) / 10000000 * 10000000 startNS, 26 sum(event_count) event_count, 27 count(event_count) sample_count, 28 event_type_id 29 from perf_sample sp 30 where sp.thread_id = ${args.tid} 31 and sp.thread_id != 0 ${args.drawType >= 0 ? 'and event_type_id =' + args.drawType : ''} 32 group by startNS) 33 where startNS + 10000000 >= ${Math.floor(args.startNS)} 34 and startNS <= ${Math.floor(args.endNS)} 35 group by px;`; 36}; 37export const chartHiperfThreadDataProtoSql = (args: Args): string => { 38 return `SELECT (sp.timestamp_trace - ${args.recordStartNS} 39 ) startNS, 40 event_count as eventCount, 41 1 as sampleCount, 42 event_type_id as eventTypeId, 43 sp.callchain_id as callchainId, 44 (sp.timestamp_trace - ${args.recordStartNS}) / (${Math.floor( 45 (args.endNS - args.startNS) / args.width 46 )}) AS px 47 from perf_sample sp 48 where sp.thread_id = ${args.tid} 49 and sp.thread_id != 0 ${args.drawType >= 0 ? 'and event_type_id =' + args.drawType : ''} 50 and startNS >= ${Math.floor(args.startNS)} 51 and startNS <= ${Math.floor(args.endNS)} 52 group by px;`; 53}; 54 55export function hiperfThreadDataReceiver(data: unknown, proc: Function): void { 56 let sql: string; 57 // @ts-ignore 58 if (data.params.scale > 30_000_000) { 59 // @ts-ignore 60 sql = chartHiperfThreadData10MSProtoSql(data.params); 61 } else { 62 // @ts-ignore 63 sql = chartHiperfThreadDataProtoSql(data.params); 64 } 65 let res = proc(sql); 66 // @ts-ignore 67 arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); 68} 69 70function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean): void { 71 // @ts-ignore 72 let maxCpuCount = data.params.maxCpuCount; 73 // @ts-ignore 74 let intervalPerf = data.params.intervalPerf; 75 // @ts-ignore 76 let usage = data.params.drawType === -2; 77 let perfThread = new PerfThread(data, transfer, res.length); 78 let maxEventCount = Math.max( 79 ...res.map((it) => { 80 // @ts-ignore 81 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.hiperfData); 82 // @ts-ignore 83 return it.eventCount; 84 }) 85 ); 86 res.forEach((it, i) => { 87 // @ts-ignore 88 data.params.trafic === TraficEnum.ProtoBuffer && (it = it.hiperfData); 89 // @ts-ignore 90 perfThread.startNS[i] = it.startNS || it.startNs; 91 // @ts-ignore 92 perfThread.eventCount[i] = it.eventCount; 93 // @ts-ignore 94 perfThread.sampleCount[i] = it.sampleCount; 95 // @ts-ignore 96 perfThread.eventTypeId[i] = it.eventTypeId; 97 // @ts-ignore 98 perfThread.callChainId[i] = it.callchainId; 99 if (usage) { 100 perfThread.height[i] = 101 maxCpuCount === -1 102 ? // @ts-ignore 103 Math.floor((it.sampleCount / (10 / intervalPerf)) * 40) 104 : // @ts-ignore 105 Math.floor((it.sampleCount / (10 / intervalPerf) / maxCpuCount) * 40); 106 } else { 107 // @ts-ignore 108 perfThread.height[i] = Math.floor((it.eventCount / maxEventCount) * 40); 109 } 110 }); 111 postPerfThreadMessage(data, transfer, perfThread, res.length); 112} 113function postPerfThreadMessage(data: unknown, transfer: boolean, perfThread: PerfThread, len: number): void { 114 (self as unknown as Worker).postMessage( 115 { 116 // @ts-ignore 117 id: data.id, 118 // @ts-ignore 119 action: data.action, 120 results: transfer 121 ? { 122 startNS: perfThread.startNS.buffer, 123 eventCount: perfThread.eventCount.buffer, 124 sampleCount: perfThread.sampleCount.buffer, 125 eventTypeId: perfThread.eventTypeId.buffer, 126 callChainId: perfThread.callChainId.buffer, 127 height: perfThread.height.buffer, 128 } 129 : {}, 130 len: len, 131 transfer: transfer, 132 }, 133 transfer 134 ? [ 135 perfThread.startNS.buffer, 136 perfThread.eventCount.buffer, 137 perfThread.sampleCount.buffer, 138 perfThread.eventTypeId.buffer, 139 perfThread.callChainId.buffer, 140 perfThread.height.buffer, 141 ] 142 : [] 143 ); 144} 145class PerfThread { 146 startNS: Float64Array; 147 eventCount: Int32Array; 148 sampleCount: Int32Array; 149 eventTypeId: Int32Array; 150 callChainId: Int32Array; 151 height: Int32Array; 152 constructor(data: unknown, transfer: boolean, len: number) { 153 // @ts-ignore 154 this.startNS = new Float64Array(transfer ? len : data.params.sharedArrayBuffers.startNS); 155 // @ts-ignore 156 this.eventCount = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.eventCount); 157 // @ts-ignore 158 this.sampleCount = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.sampleCount); 159 // @ts-ignore 160 this.eventTypeId = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.eventTypeId); 161 // @ts-ignore 162 this.callChainId = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.callChainId); 163 // @ts-ignore 164 this.height = new Int32Array(transfer ? len : data.params.sharedArrayBuffers.height); 165 } 166} 167