• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16class PerfCallChainThread {
17  taskMap: unknown = {};
18  worker?: Worker;
19  busy: boolean = false;
20
21  constructor(worker: Worker) {
22    this.worker = worker;
23  }
24
25  uuid(): string {
26    // @ts-ignore
27    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: number) =>
28      (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
29    );
30  }
31
32  queryFunc(name: string, args: unknown, handler: Function, action: string | null): void {
33    this.busy = true;
34    let id = this.uuid();
35    // @ts-ignore
36    this.taskMap[id] = handler;
37    let msg = {
38      id: id,
39      name: name,
40      action: action || 'exec',
41      params: args,
42    };
43    this.worker!.postMessage(msg);
44  }
45}
46
47export class PerfCallChainPool {
48  maxThreadNumber: number = 0;
49  works: Array<PerfCallChainThread> = [];
50
51  close = async (): Promise<void> => {
52    for (let i = 0; i < this.works.length; i++) {
53      let thread = this.works[i];
54      thread.worker!.terminate();
55    }
56    this.works.length = 0;
57  };
58
59  init = async (): Promise<void> => {
60    await this.close();
61    let thread = new PerfCallChainThread(
62      new Worker(new URL('../../component/chart/PerfDataQuery', import.meta.url), { type: 'module' })
63    );
64    thread!.worker!.onmessage = (event: MessageEvent): void => {
65      thread.busy = false;
66      // @ts-ignore
67      let fun = thread.taskMap[event.data.id];
68      if (fun) {
69        fun(event.data.results);
70      }
71      // @ts-ignore
72      Reflect.deleteProperty(thread.taskMap, event.data.id);
73    };
74    thread!.worker!.onmessageerror = (e): void => {};
75    thread!.worker!.onerror = (e): void => {};
76    thread!.busy = false;
77    this.works?.push(thread!);
78  };
79
80  submit(name: string, args: unknown, handler: Function, action: string | null): void {
81    let noBusyThreads = this.works.filter((it) => !it.busy);
82    let thread: PerfCallChainThread;
83    if (noBusyThreads.length > 0) {
84      //取第一个空闲的线程进行任务
85      thread = noBusyThreads[0];
86      thread.queryFunc(name, args, handler, action);
87    } else {
88      // 随机插入一个线程中
89      thread = this.works[Math.floor(Math.random() * this.works.length)];
90      thread.queryFunc(name, args, handler, action);
91    }
92  }
93}
94
95export const callChainsPool = new PerfCallChainPool();
96