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