diff --git a/compiler/src/gen_abc.ts b/compiler/src/gen_abc.ts index dd923af2fd8ff91738d964f1a363da1209b32eec..8d20e07a55607165320f5398c414600cfc5c1b74 100644 --- a/compiler/src/gen_abc.ts +++ b/compiler/src/gen_abc.ts @@ -1,23 +1,35 @@ -import * as process from 'child_process'; +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as childProcess from 'child_process'; +import * as process from 'process'; import * as fs from 'fs'; +import cluster from 'cluster'; import { logger } from './compile_info'; -const {workerData, threadId} = require('worker_threads'); - -interface File { - path: string, - size: number -} const red: string = '\u001b[31m'; const reset: string = '\u001b[39m'; -function js2abcByWorkers(inputPaths: File[], cmd: string): Promise { +function js2abcByWorkers(jsonInput: string, cmd: string): Promise { + const inputPaths = JSON.parse(jsonInput); for (let i = 0; i < inputPaths.length; ++i) { - let input = inputPaths[i].path; - let singleCmd = `${cmd} "${input}"`; - logger.debug("gen abc cmd is: ", singleCmd); + const input = inputPaths[i].path; + const singleCmd = `${cmd} "${input}"`; + logger.debug("gen abc cmd is: ", singleCmd, " ,file size is:", inputPaths[i].size, " byte"); try { - process.execSync(singleCmd); + childProcess.execSync(singleCmd); } catch (e) { logger.error(red, `ETS:ERROR Failed to convert file ${input} to abc `, reset); return; @@ -37,8 +49,10 @@ function js2abcByWorkers(inputPaths: File[], cmd: string): Promise { } } -logger.debug("worker data is: ", JSON.stringify(workerData)); -if (JSON.stringify(workerData) !== 'null') { - logger.debug("==>worker #", threadId, "started!"); - js2abcByWorkers(workerData.input, workerData.cmd); +logger.debug("worker data is: ", JSON.stringify(process.env)); +logger.debug("gen_abc isWorker is: ", cluster.isWorker); +if (cluster.isWorker && process.env["inputs"] !== undefined && process.env["cmd"] !== undefined) { + logger.debug("==>worker #", cluster.worker.id, "started!"); + js2abcByWorkers(process.env["inputs"], process.env["cmd"]); + process.exit(); } diff --git a/compiler/src/gen_abc_plugin.ts b/compiler/src/gen_abc_plugin.ts index 1565e11c327430fea1b8fe9034d4ef3b578f8a03..59a3b326d278630b330b1437051b04ccc620e2fd 100644 --- a/compiler/src/gen_abc_plugin.ts +++ b/compiler/src/gen_abc_plugin.ts @@ -15,10 +15,11 @@ import * as fs from 'fs'; import * as path from 'path'; +import cluster from 'cluster'; +import * as process from 'process'; import Compiler from 'webpack/lib/Compiler'; import { logger } from './compile_info'; -const {Worker, isMainThread} = require('worker_threads'); const firstFileEXT: string = '_.js'; const genAbcScript = 'gen_abc.js'; let output: string; @@ -70,31 +71,7 @@ export class GenAbcPlugin { }); compiler.hooks.afterEmit.tap('GenAbcPluginMultiThread', () => { - let param: string = ''; - if (isDebug) { - param += ' --debug'; - } - - if (isMainThread) { - let js2abc: string = path.join(arkDir, 'build', 'src', 'index.js'); - if (isWin) { - js2abc = path.join(arkDir, 'build-win', 'src', 'index.js'); - } else if (isMac) { - js2abc = path.join(arkDir, 'build-mac', 'src', 'index.js'); - } - let maxWorkerNumber = 3; - let splitedBundles = splitJsBundlesBySize(intermediateJsBundle, maxWorkerNumber); - let workerNumber = maxWorkerNumber < splitedBundles.length ? maxWorkerNumber : splitedBundles.length; - let cmdPrefix: string = `${nodeJs} --expose-gc "${js2abc}" ${param} `; - let workers = []; - for (let i = 0; i < workerNumber; ++i) { - workers.push(new Worker(path.resolve(__dirname, genAbcScript), - {workerData: {input: splitedBundles[i], cmd: cmdPrefix} })); - workers[i].on('exit', () => { - logger.debug("worker ", i, "finished!"); - }); - } - } + invokeWorkersToGenAbc(); }); } } @@ -124,12 +101,12 @@ function mkDir(path_: string): void { function getSmallestSizeGroup(groupSize: Map) { let groupSizeArray = Array.from(groupSize); groupSizeArray.sort(function(g1, g2) { - return g1[1] - g2[1]; // sort by value + return g1[1] - g2[1]; // sort by size }); - return groupSizeArray[0][0]; // return key + return groupSizeArray[0][0]; } -function splitJsBundlesBySize(bundleArray: Array, groupNumber: number){ +function splitJsBundlesBySize(bundleArray: Array, groupNumber: number) { let result = []; if (bundleArray.length < groupNumber) { result.push(bundleArray); @@ -155,3 +132,50 @@ function splitJsBundlesBySize(bundleArray: Array, groupNumber: number){ } return result; } + +function invokeWorkersToGenAbc() { + let param: string = ''; + if (isDebug) { + param += ' --debug'; + } + + let js2abc: string = path.join(arkDir, 'build', 'src', 'index.js'); + if (isWin) { + js2abc = path.join(arkDir, 'build-win', 'src', 'index.js'); + } else if (isMac) { + js2abc = path.join(arkDir, 'build-mac', 'src', 'index.js'); + } + + const maxWorkerNumber = 3; + const splitedBundles = splitJsBundlesBySize(intermediateJsBundle, maxWorkerNumber); + const workerNumber = maxWorkerNumber < splitedBundles.length ? maxWorkerNumber : splitedBundles.length; + const cmdPrefix: string = `${nodeJs} --expose-gc "${js2abc}" ${param} `; + + const clusterNewApiVersion = 16; + const currentNodeVersion = parseInt(process.version.split('.')[0]); + const useNewApi = currentNodeVersion >= clusterNewApiVersion ? true : false; + + if ((useNewApi && cluster.isPrimary) || (!useNewApi && cluster.isMaster)) { + if (useNewApi) { + cluster.setupPrimary({ + exec: path.resolve(__dirname, genAbcScript) + }); + } else { + cluster.setupMaster({ + exec: path.resolve(__dirname, genAbcScript) + }); + } + + for (let i = 0; i < workerNumber; ++i) { + let workerData = { + "inputs": JSON.stringify(splitedBundles[i]), + "cmd": cmdPrefix + } + cluster.fork(workerData); + } + + cluster.on('exit', (worker, code, signal) => { + logger.debug(`worker ${worker.process.pid} finished`); + }); + } +}