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 extends Worker { 17 busy: boolean = false; 18 taskMap: any = {}; 19 uuid(): string { 20 // @ts-ignore 21 return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: any) => 22 (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 23 ); 24 } 25 26 queryFunc(name: string, args: any, handler: Function, action: string | null) { 27 this.busy = true; 28 let id = this.uuid(); 29 this.taskMap[id] = handler; 30 let msg = { 31 id: id, 32 name: name, 33 action: action || 'exec', 34 params: args, 35 }; 36 this.postMessage(msg); 37 } 38} 39 40export class PerfCallChainPool { 41 maxThreadNumber: number = 0; 42 works: Array<PerfCallChainThread> = []; 43 44 close = async () => { 45 for (let i = 0; i < this.works.length; i++) { 46 let thread = this.works[i]; 47 thread.terminate(); 48 } 49 this.works.length = 0; 50 }; 51 52 init = async () => { 53 await this.close(); 54 let thread = new PerfCallChainThread('trace/component/chart/PerfDataQuery.js', { type: 'module' }); //trace/component/chart/PerfDataQuery.js 55 thread!.onmessage = (event: MessageEvent) => { 56 thread.busy = false; 57 let fun = thread.taskMap[event.data.id]; 58 if (fun) { 59 fun(event.data.results); 60 } 61 Reflect.deleteProperty(thread.taskMap, event.data.id); 62 }; 63 thread!.onmessageerror = (e) => {}; 64 thread!.onerror = (e) => {}; 65 thread!.busy = false; 66 this.works?.push(thread!); 67 }; 68 69 submit(name: string, args: any, handler: Function, action: string | null) { 70 let noBusyThreads = this.works.filter((it) => !it.busy); 71 let thread: PerfCallChainThread; 72 if (noBusyThreads.length > 0) { 73 //取第一个空闲的线程进行任务 74 thread = noBusyThreads[0]; 75 thread.queryFunc(name, args, handler, action); 76 } else { 77 // 随机插入一个线程中 78 thread = this.works[Math.floor(Math.random() * this.works.length)]; 79 thread.queryFunc(name, args, handler, action); 80 } 81 } 82} 83 84export const callChainsPool = new PerfCallChainPool(); 85