diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts index 11ff17da092d9d405859903afc296206bfd0c7e4..a94a03cfe39487557667b5c30ee1bb6e78ada14e 100644 --- a/app/modules/prover/lib/blockProver.ts +++ b/app/modules/prover/lib/blockProver.ts @@ -48,6 +48,14 @@ export class WorkerFarm { return this.theEngine.getNbWorkers() } + reduceNbCores() { + return this.theEngine.reduceNbCores() + } + + boostCPU(){ + return this.theEngine.boostCPU() + } + changeCPU(cpu:any) { return this.theEngine.setConf({ cpu }) } @@ -194,13 +202,12 @@ export class BlockProver { }); if (!result) { this.logger.info('GIVEN proof-of-work for block#%s with %s leading zeros followed by [0-' + highMark + ']! stop PoW for %s', block.number, nbZeros, this.pair && this.pair.pub.slice(0,6)); - let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey) if(this.conf.ecoMode === true) { let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey) if(selfNbBlockInFrame < 2) { - this.changeCPU(1) - this.conf.nbCores = this.server.conf.nbCores - this.logger.info("Boost number of CPU cores "+this.conf.nbCores+" with only "+selfNbBlockInFrame+" block member in frame") + this.boostCPU() + this.conf.nbCores = powFarm.nbWorkers + this.logger.info("Boost number of CPU cores "+powFarm.nbWorkers+" with only "+selfNbBlockInFrame+" block member in frame") } } throw 'Proof-of-work computation canceled because block received'; @@ -214,14 +221,15 @@ export class BlockProver { if(this.conf.ecoMode === true) { let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey) if(selfNbBlockInFrame < 2) { - this.changeCPU(1) - this.conf.nbCores = this.server.conf.nbCores - this.logger.info("Boost number of CPU cores "+this.conf.nbCores+" with only "+selfNbBlockInFrame+" block member in frame") + this.boostCPU() + this.conf.nbCores = powFarm.nbWorkers + this.logger.info("Boost number of CPU cores "+powFarm.nbWorkers+" with only "+selfNbBlockInFrame+" block member in frame") } - else if(this.conf.nbCores*testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) { - if(this.conf.nbCores > 1) { - this.logger.info("Reducing number of CPU cores "+this.conf.nbCores) - this.conf.nbCores = this.conf.nbCores -1 + else if(testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) { + if(powFarm.nbWorkers > 1) { + this.logger.info("Reducing number of CPU cores "+powFarm.nbWorkers) + this.reduceNbCores() + this.conf.nbCores = powFarm.nbWorkers } else if(this.conf.cpu > ProverConstants.ECO_MODE_MINIMAL_CPU){ let cpu:number = this.conf.cpu - 0.1 @@ -235,6 +243,17 @@ export class BlockProver { })() }; + async reduceNbCores() { + const farm = await this.getWorker() + return farm.reduceNbCores() + } + + async boostCPU() { + this.conf.cpu = 1.0 + const farm = await this.getWorker() + return farm.boostCPU() + } + async changeCPU(cpu:number) { this.conf.cpu = Math.max(0.01, Math.min(1.0, cpu)); const farm = await this.getWorker() diff --git a/app/modules/prover/lib/engine.ts b/app/modules/prover/lib/engine.ts index 6ab1ca6458f52047e3e2dfa2548b1fd73f316ed9..64bd629f3e6ba60c66f69bb48122fbe7f0fa598a 100644 --- a/app/modules/prover/lib/engine.ts +++ b/app/modules/prover/lib/engine.ts @@ -12,15 +12,12 @@ if(debug) { export class PowEngine { - private nbWorkers:number private cluster:PowCluster readonly id:number constructor(private conf:ConfDTO, logger:any) { - // We use as much cores as available, but not more than CORES_MAXIMUM_USE_IN_PARALLEL - this.nbWorkers = conf.nbCores - this.cluster = new PowCluster(this.nbWorkers, logger) + this.cluster = new PowCluster(conf.nbCores, logger) this.id = this.cluster.clusterId } @@ -41,6 +38,14 @@ export class PowEngine { return this.cluster.cancelWork() } + reduceNbCores() { + return this.cluster.removeSlave() + } + + boostCPU() { + return this.cluster.boostCPU() + } + setConf(value:any) { return this.cluster.changeConf(value) } diff --git a/app/modules/prover/lib/powCluster.ts b/app/modules/prover/lib/powCluster.ts index d0c64c4e422ff0d95111d2d2f491e97d38a06967..fc3821043bed888863081ba9f37c582cfedfdafc 100644 --- a/app/modules/prover/lib/powCluster.ts +++ b/app/modules/prover/lib/powCluster.ts @@ -35,6 +35,7 @@ export class Master { logger:any onInfoCallback:any workersOnline:Promise<any>[] + maxNbCores:number = Math.min(ProverConstants.CORES_MAXIMUM_USE_IN_PARALLEL, require('os').cpus().length) constructor(private nbCores:number, logger:any) { this.clusterId = clusterId++ @@ -65,6 +66,56 @@ export class Master { // this.logger.debug(`ENGINE c#${this.clusterId}#${this.slavesMap[worker.id].index}:`, message) } + createSlave(index:number) { + const nodejsWorker = cluster.fork() + const worker = new PowWorker(nodejsWorker, message => { + this.onWorkerMessage(index, message) + }, () => { + this.logger.info(`[online] worker c#${this.clusterId}#w#${index}`) + worker.sendConf({ + command: 'conf', + value: this.conf + }) + }, (code:any, signal:any) => { + this.logger.info(`worker ${worker.pid} died with code ${code} and signal ${signal}`) + }) + + this.logger.info(`Creating worker c#${this.clusterId}#w#${nodejsWorker.id}`) + const slave = { + + // The Node.js worker + worker, + + // Inner identifier + index, + + // Worker ready + online: worker.online, + + // Each worker has his own chunk of possible nonces + nonceBeginning: this.nbCores === 1 ? 0 : (index + 1) * ProverConstants.NONCE_RANGE + } + this.slavesMap[nodejsWorker.id] = slave + return slave + } + + boostCPU() { + if(this.nbWorkers < this.maxNbCores) { + while(this.nbWorkers < this.maxNbCores) { + this.slaves.push(this.createSlave(this.nbWorkers)) + } + } + let conf:any = {cpu: 1} + this.changeConf(conf) + } + + async removeSlave() { + let nb_workers = this.nbWorkers + await this.slaves[nb_workers-1].worker.kill() + this.slaves.pop() + this.logger.info('Remove slave number '+ (nb_workers-1)) + } + /***************** * CLUSTER METHODS ****************/ @@ -77,36 +128,7 @@ export class Master { }) this.slaves = Array.from({ length: this.nbCores }).map((value, index) => { - const nodejsWorker = cluster.fork() - const worker = new PowWorker(nodejsWorker, message => { - this.onWorkerMessage(index, message) - }, () => { - this.logger.info(`[online] worker c#${this.clusterId}#w#${index}`) - worker.sendConf({ - command: 'conf', - value: this.conf - }) - }, (code:any, signal:any) => { - this.logger.info(`worker ${worker.pid} died with code ${code} and signal ${signal}`) - }) - - this.logger.info(`Creating worker c#${this.clusterId}#w#${nodejsWorker.id}`) - const slave = { - - // The Node.js worker - worker, - - // Inner identifier - index, - - // Worker ready - online: worker.online, - - // Each worker has his own chunk of possible nonces - nonceBeginning: this.nbCores === 1 ? 0 : (index + 1) * ProverConstants.NONCE_RANGE - } - this.slavesMap[nodejsWorker.id] = slave - return slave + return this.createSlave(index) }) this.workersOnline = this.slaves.map((s) => s.online)