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