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