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';
15import { filterDataByGroup } from './utils/DataFilter';
16import { cpuList } from './utils/AllMemoryCache';
17import { Args } from './CommonArgs';
18
19export const chartCpuDataProtoSql = (args: Args): string => {
20  return `
21      SELECT B.pid                                                                                        as processId,
22             B.cpu,
23             B.tid,
24             B.itid                                                                                       as id,
25             max(B.dur)                                                                                   AS dur,
26             B.ts - ${args.recordStartNS}                                                                 AS startTime,
27             ifnull(B.arg_setid, -1)                                                                      as argSetId,
28             ((B.ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px
29      from thread_state AS B
30      where B.itid is not null
31        and B.cpu = ${args.cpu}
32        and startTime + dur >= ${Math.floor(args.startNS)}
33        and startTime <= ${Math.floor(args.endNS)}
34      group by px;`;
35};
36
37export const chartCpuDataProtoSqlMem = (args: Args): string => {
38  return `
39      SELECT B.pid                        as processId,
40             B.cpu,
41             B.tid,
42             B.itid                       as id,
43             B.dur                        AS dur,
44             B.ts - ${args.recordStartNS} AS startTime,
45             ifnull(B.arg_setid, -1)      as argSetId
46      from thread_state AS B
47      where B.itid is not null
48        and B.cpu = ${args.cpu};`;
49};
50
51export function cpuDataReceiver(data: unknown, proc: Function): void {
52  // @ts-ignore
53  if (data.params.trafic === TraficEnum.Memory) {
54    let res: unknown[];
55    let list: unknown[];
56    // @ts-ignore
57    if (!cpuList.has(data.params.cpu)) {
58      // @ts-ignore
59      list = proc(chartCpuDataProtoSqlMem(data.params));
60      for (let i = 0; i < list.length; i++) {
61        // @ts-ignore
62        if (list[i].dur === -1 || list[i].dur === null || list[i].dur === undefined) {
63          // @ts-ignore
64          list[i].nofinish = 1;
65          if (i === list.length - 1) {
66            // @ts-ignore
67            list[i].dur = data.params.endNS - list[i].startTime;
68          } else {
69            // @ts-ignore
70            list[i].dur = list[i + 1].startTime - list[i].startTime;
71          }
72        } else {
73          // @ts-ignore
74          list[i].nofinish = 0;
75        }
76      }
77      // @ts-ignore
78      cpuList.set(data.params.cpu, list);
79    } else {
80      // @ts-ignore
81      list = cpuList.get(data.params.cpu) || [];
82    }
83    // @ts-ignore
84    res = filterDataByGroup(list || [], 'startTime', 'dur', data.params.startNS, data.params.endNS, data.params.width);
85    arrayBufferHandler(data, res, true);
86  } else {
87    // @ts-ignore
88    let sql = chartCpuDataProtoSql(data.params);
89    let res = proc(sql);
90    // @ts-ignore
91    arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer);
92  }
93}
94
95export function searchDataHandler(data: unknown): void {
96  let res: unknown[] = [];
97  // @ts-ignore
98  let pidArr = data.params.pidArr as number[];
99  // @ts-ignore
100  let tidArr = data.params.tidArr as number[];
101  for (let value of Array.from(cpuList.values())) {
102    res.push(
103      //@ts-ignore
104      ...value.filter((cpuData) => pidArr.includes(cpuData.pid || cpuData.processId) || tidArr.includes(cpuData.tid))
105    );
106  }
107  // @ts-ignore
108  res.sort((dataA, dataB) => dataA.startTime - dataB.startTime);
109  arrayBufferHandler(data, res, true);
110}
111
112function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean): void {
113  // @ts-ignore
114  let startTime = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTime);
115  // @ts-ignore
116  let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur);
117  // @ts-ignore
118  let tid = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.tid);
119  // @ts-ignore
120  let id = new Uint16Array(transfer ? res.length : data.params.sharedArrayBuffers.id);
121  // @ts-ignore
122  let processId = new Int16Array(transfer ? res.length : data.params.sharedArrayBuffers.processId);
123  // @ts-ignore
124  let cpu = new Uint8Array(transfer ? res.length : data.params.sharedArrayBuffers.cpu);
125  // @ts-ignore
126  let argSetId = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.argSetId);
127  // @ts-ignore
128  let nofinish = new Uint8Array(transfer ? res.length : data.params.sharedArrayBuffers.nofinish);
129  res.forEach((it, i) => {
130    // @ts-ignore
131    data.params.trafic === TraficEnum.ProtoBuffer && (it = it.cpuData);
132    // @ts-ignore
133    startTime[i] = it.startTime;
134    // @ts-ignore
135    dur[i] = it.dur;
136    // @ts-ignore
137    tid[i] = it.tid;
138    // @ts-ignore
139    cpu[i] = it.cpu;
140    // @ts-ignore
141    id[i] = it.id;
142    // @ts-ignore
143    nofinish[i] = it.nofinish;
144    // @ts-ignore
145    processId[i] = it.pid || it.processId;
146    // @ts-ignore
147    argSetId[i] = it.argSetId;
148  });
149  (self as unknown as Worker).postMessage(
150    {
151      // @ts-ignore
152      id: data.id,
153      // @ts-ignore
154      action: data.action,
155      results: transfer
156        ? {
157            startTime: startTime.buffer,
158            dur: dur.buffer,
159            tid: tid.buffer,
160            id: id.buffer,
161            processId: processId.buffer,
162            cpu: cpu.buffer,
163            argSetID: argSetId.buffer,
164            nofinish: nofinish.buffer,
165          }
166        : {},
167      len: res.length,
168      transfer: transfer,
169    },
170    transfer
171      ? [
172          startTime.buffer,
173          dur.buffer,
174          tid.buffer,
175          id.buffer,
176          processId.buffer,
177          cpu.buffer,
178          argSetId.buffer,
179          nofinish.buffer,
180        ]
181      : []
182  );
183}
184