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 16importScripts('trace_converter_builtin.js'); 17self.onerror = function (error: any) {}; 18 19let convertModule: any = null; 20 21function initConvertWASM() { 22 return new Promise((resolve, reject) => { 23 // @ts-ignore 24 let wasm = trace_converter_builtin_wasm; 25 convertModule = wasm({ 26 locateFile: (s: any) => { 27 return s; 28 }, 29 print: (line: any) => {}, 30 printErr: (line: any) => {}, 31 onAbort: () => { 32 reject('on abort'); 33 }, 34 onRuntimeInitialized: () => { 35 resolve('ok'); 36 }, 37 }); 38 }); 39} 40 41const ARRAY_BUF_SIZE = 2 * 1024 * 1024; 42self.onmessage = async (e: MessageEvent) => { 43 if (e.data.action === 'getConvertData') { 44 await initConvertWASM(); 45 let fileData = e.data.buffer; 46 const stepSize = 4 * 1024 * 1024; 47 let totalSize = fileData.byteLength; 48 let traceInsPtr = convertModule._GetTraceConverterIns(); // 获取TraceConverter 实例 49 convertModule._SetDebugFlag(false, traceInsPtr); // 设置是否为debug模式 50 let uint8Array = new Uint8Array(fileData.slice(0, 8)); // 获取前8个字节,用来判断文件是htrace还是raw trace 51 let enc = new TextDecoder(); 52 let headerStr = enc.decode(uint8Array); 53 let currentPosition = 1024; 54 let dataHeader = convertModule._malloc(1100); 55 let traceAllData = new Uint8Array(e.data.buffer); 56 if (headerStr.indexOf('OHOSPROF') === 0) { 57 handleHTrace(fileData, dataHeader, traceInsPtr); 58 } else { 59 handleRowTrace(e, fileData, dataHeader, traceInsPtr, currentPosition, traceAllData, totalSize); 60 } 61 let dataPtr = convertModule._malloc(stepSize); 62 let arrayBufferPtr = convertModule._malloc(ARRAY_BUF_SIZE); 63 convertModule._free(dataHeader); 64 let bodyDataStr: string[] = []; 65 let callback = (heapPtr: number, size: number) => { 66 let out = convertModule.HEAPU8.slice(heapPtr, heapPtr + size); 67 let dec = new TextDecoder(); 68 let str = dec.decode(out); 69 bodyDataStr.push(str); 70 }; 71 let bodyFn = convertModule.addFunction(callback, 'vii'); 72 convertModule._SetCallback(bodyFn, traceInsPtr); 73 convertData(currentPosition, traceAllData, arrayBufferPtr, dataPtr, traceInsPtr, headerStr, stepSize, totalSize); 74 convertModule._GetRemainingData(traceInsPtr); 75 let headerData: string[] = []; 76 let headerCallback = (heapPtr: number, size: number) => { 77 let out = convertModule.HEAPU8.slice(heapPtr, heapPtr + size); 78 let dec = new TextDecoder(); 79 let str = dec.decode(out); 80 headerData.push(str); 81 }; 82 let headerFn = convertModule.addFunction(headerCallback, 'vii'); 83 convertModule._SetCallback(headerFn, traceInsPtr); 84 convertModule._GetFinalHeader(traceInsPtr); 85 let allDataStr = headerData.concat(bodyDataStr); 86 convertModule._ReleaseTraceConverterIns(traceInsPtr); // 释放TraceConverter 实例 87 convertModule._free(arrayBufferPtr); //释放分片内存 88 convertModule._free(dataPtr); 89 postMessage(e, allDataStr); 90 } 91}; 92function handleHTrace(fileData: Array<any>, dataHeader: any, traceInsPtr: any) { 93 let uint8Array = new Uint8Array(fileData.slice(0, 1024)); 94 convertModule.HEAPU8.set(uint8Array, dataHeader); 95 convertModule._SendFileHeader(dataHeader, 1024, traceInsPtr); 96} 97function handleRowTrace( 98 e: MessageEvent, 99 fileData: Array<any>, 100 dataHeader: any, 101 traceInsPtr: any, 102 currentPosition: number, 103 traceAllData: Uint8Array, 104 totalSize: number 105): void { 106 let uint8Array = new Uint8Array(fileData.slice(0, 12)); 107 convertModule.HEAPU8.set(uint8Array, dataHeader); 108 convertModule._SendRawFileHeader(dataHeader, 12, traceInsPtr); 109 currentPosition = 12; 110 let allRowTraceData = new Uint8Array(e.data.buffer); 111 let commonDataOffsetList: Array<{ 112 startOffset: number; 113 endOffset: number; 114 }> = []; 115 let commonTotalLength = 0; 116 setCommonDataOffsetList(e, allRowTraceData, commonTotalLength, commonDataOffsetList); 117 let commonTotalOffset = 0; 118 let commonTotalData = new Uint8Array(commonTotalLength); 119 commonDataOffsetList.forEach((item) => { 120 commonTotalData.set(allRowTraceData.slice(item.startOffset, item.endOffset), commonTotalOffset); 121 commonTotalOffset += item.endOffset - item.startOffset; 122 }); 123 traceAllData = new Uint8Array(allRowTraceData.length + commonTotalData.length); 124 traceAllData.set(allRowTraceData.slice(0, currentPosition), 0); 125 traceAllData.set(commonTotalData, currentPosition); 126 traceAllData.set(allRowTraceData.slice(currentPosition), commonTotalData.length + currentPosition); 127 totalSize += commonTotalData.length; 128} 129function setCommonDataOffsetList( 130 e: MessageEvent, 131 allRowTraceData: Uint8Array, 132 commonTotalLength: number, 133 commonDataOffsetList: Array<any> 134): void { 135 let commonOffset = 12; 136 let tlvTypeLength = 4; 137 while (commonOffset < allRowTraceData.length) { 138 let commonDataOffset = { 139 startOffset: commonOffset, 140 endOffset: commonOffset, 141 }; 142 let dataTypeData = e.data.buffer.slice(commonOffset, commonOffset + tlvTypeLength); 143 commonOffset += tlvTypeLength; 144 let dataType = Array.from(new Uint32Array(dataTypeData)); 145 let currentLData = e.data.buffer.slice(commonOffset, commonOffset + tlvTypeLength); 146 commonOffset += tlvTypeLength; 147 let currentVLength = Array.from(new Uint32Array(currentLData)); 148 commonOffset += currentVLength[0]; 149 commonDataOffset.endOffset = commonOffset; 150 if (dataType[0] === 2 || dataType[0] === 3) { 151 commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; 152 commonDataOffsetList.push(commonDataOffset); 153 } 154 } 155} 156function convertData( 157 currentPosition: number, 158 traceAllData: Uint8Array, 159 arrayBufferPtr: any, 160 dataPtr: any, 161 traceInsPtr: any, 162 headerStr: string, 163 stepSize: number, 164 totalSize: number 165): void { 166 while (currentPosition < totalSize) { 167 let endPosition = Math.min(currentPosition + stepSize, totalSize); 168 let currentChunk = new Uint8Array(traceAllData.slice(currentPosition, endPosition)); 169 convertModule.HEAPU8.set(currentChunk, dataPtr); 170 let leftLen = currentChunk.length; 171 let processedLen = 0; 172 let blockSize = 0; 173 let blockPtr = dataPtr; 174 while (leftLen > 0) { 175 if (leftLen > ARRAY_BUF_SIZE) { 176 blockSize = ARRAY_BUF_SIZE; 177 } else { 178 blockSize = leftLen; 179 } 180 let subArrayBuffer = convertModule.HEAPU8.subarray(blockPtr, blockPtr + blockSize); 181 convertModule.HEAPU8.set(subArrayBuffer, arrayBufferPtr); 182 // 调用分片转换接口 183 if (headerStr.indexOf('OHOSPROF') === 0) { 184 // htrace 185 convertModule._ConvertBlockData(arrayBufferPtr, subArrayBuffer.length, traceInsPtr); 186 } else { 187 // raw trace 188 convertModule._ConvertRawBlockData(arrayBufferPtr, subArrayBuffer.length, traceInsPtr); 189 } 190 processedLen = processedLen + blockSize; 191 blockPtr = dataPtr + processedLen; 192 leftLen = currentChunk.length - processedLen; 193 } 194 currentPosition = endPosition; 195 } 196} 197function postMessage(e: MessageEvent, allDataStr: Array<string>): void { 198 self.postMessage( 199 { 200 id: e.data.id, 201 action: 'convert', 202 status: true, 203 results: new Blob(allDataStr, { type: 'text/plain' }), 204 buffer: e.data.buffer, 205 }, 206 // @ts-ignore 207 [e.data.buffer!] 208 ); 209} 210