自动将node.js类转换为worker

8yoxcaq7  于 2023-05-22  发布在  Node.js
关注(0)|答案(1)|浏览(83)

我有一个耗时的任务要在node.js服务器上执行。我想测试它在一个单独的线程中运行时的性能。我想从一个工人暴露类,而不必手动编码的每一部分。有没有一个节点内部函数或模块可以做到这一点?谢谢

class RunInWorker {

  constructor (starta, startb) {
    this.sum = starta + startb;
  }

  addSync(a, b) {
    return a + b + this.sum;
  }

  async addAsync(a, b) {
    await (new Promise((resolve) => { setTimeout(resolve, 3000); }));
    return a + b + this.sum;
  }

}

/** @type {\RunInWorker} */
let worker = new require('./wrap-worker.js')(RunInWorker, [5, 5]);

(async () => {
  console.log(worker);
  console.log(await worker.addSync(3, 4), 'should be', 17);
  console.log(await worker.addAsync(3, 8), 'should be', 21);
})();

我目前正在转换类为String,然后在运行中创建一个工人,但我不认为这是最好的方法…

// wrap-worker.js
const { Worker, isMainThread } = require('worker_threads');

function WrapWorker(OBJECT, OBJECT_ARGS) {

  if (isMainThread) {

    let workerCode = `
const { parentPort, workerData } = require('worker_threads');

let OBJECT = ` + OBJECT.toString() + `

let INSTANCE = new OBJECT(...workerData);

parentPort.on('message', async function (data) {
  if (data.method) {
    let method = INSTANCE[data.method];
    if (typeof method === 'function') {
      let response;
      if (method.constructor.name === 'AsyncFunction') response = await method.apply(INSTANCE, data.arguments);
      else response = method.apply(INSTANCE, data.arguments);
      parentPort.postMessage({ rid: data.rid, valid: 1, response: response });
    } else {
      parentPort.postMessage({ rid: data.rid, valid: 0 });
    }
  }
});`;

    let instance = new Worker(workerCode, { eval: true, workerData: OBJECT_ARGS });

    let methodsProxy = {};
    let methods = Object.getOwnPropertyNames(OBJECT.prototype);

    let rid = 0;
    let requests = [];
    for (let mid in methods) {
      let methodId = methods[mid];
      methodsProxy[methodId] = function () {
        return new Promise((resolve, reject) => {
          rid++;
          requests[rid] = { resolve: resolve, reject: reject };
          instance.postMessage({ method: methodId, arguments: Array.from(arguments), rid: rid });
        });
      };
    }

    instance.on('message', function (data) {
      if (data.rid) {
        if (data.valid) requests[data.rid].resolve(data.response);
        else requests[data.rid].reject();
        delete requests[data.rid];
      }
    });

    return methodsProxy;

  }

}

module.exports = WrapWorker;
qyuhtwio

qyuhtwio1#

// wrap-worker.js
const { Worker } = require('worker_threads');

function WrapWorker(OBJECT, OBJECT_ARGS) {
  if (require('worker_threads').isMainThread) {
    const workerCode = `
      const { parentPort, workerData } = require('worker_threads');
      const OBJECT = ${OBJECT.toString()};

      const instance = new OBJECT(...workerData);

      parentPort.on('message', async (data) => {
        try {
          const method = instance[data.method];
          if (typeof method === 'function') {
            const response = await method.apply(instance, data.arguments);
            parentPort.postMessage({ rid: data.rid, valid: true, response });
          } else {
            parentPort.postMessage({ rid: data.rid, valid: false });
          }
        } catch (error) {
          parentPort.postMessage({ rid: data.rid, valid: false });
        }
      });
    `;

    const instance = new Worker(workerCode, { eval: true, workerData: OBJECT_ARGS });

    const methodsProxy = {};
    const methods = Object.getOwnPropertyNames(OBJECT.prototype);

    let rid = 0;
    const requests = {};
    for (const methodId of methods) {
      methodsProxy[methodId] = (...args) =>
        new Promise((resolve, reject) => {
          rid++;
          requests[rid] = { resolve, reject };
          instance.postMessage({ method: methodId, arguments: args, rid });
        });
    }

    instance.on('message', (data) => {
      const request = requests[data.rid];
      if (request) {
        if (data.valid) {
          request.resolve(data.response);
        } else {
          request.reject();
        }
        delete requests[data.rid];
      }
    });

    return methodsProxy;
  }
}

module.exports = WrapWorker;

相关问题