代码之家  ›  专栏  ›  技术社区  ›  Estus Flask

节点中的I/O性能。js工作线程

  •  2
  • Estus Flask  · 技术社区  · 7 年前

    下面是一个工作线程的示例,在本地机器上同步I/O需要约600ms的时间:

    const fs = require('fs');
    const { isMainThread, Worker, parentPort, workerData } = require('worker_threads');
    
    const filename = './foo.txt';
    
    if (isMainThread) {
        (async () => {
            console.time('!');
    
            await new Promise((resolve, reject) => {
                const worker = new Worker(__filename, { workerData: filename });
    
                worker.on('message', resolve);
                worker.on('error', reject);
                worker.on('exit', (code) => {
                    if (code !== 0)
                        reject(new Error(`Worker stopped with exit code ${code}`));
                });
            });
    
            console.timeEnd('!');   
        })().catch(console.error);
    } else {
        for (let i = 0; i < 100; i++)
            fs.readFileSync(workerData);
    
        parentPort.postMessage('ok');
    }
    

    对于异步I/O,单线程的相同示例需要2秒:

    const fs = require('fs');
    
    const filename = './foo.txt';
    
    console.time('worker');
    
    (function read(i) {
        if (i < 100) {
            fs.readFile(filename, () => read(++i));
            return;
        }
    
        console.timeEnd('worker');  
    })(0);
    

    显然,同步阻塞操作在这里更有效。

    节点。js worker thread reference 各国:

    Worker对于执行CPU密集型JavaScript操作非常有用;不要将它们用于I/O,因为它们是节点。jss内置的异步执行操作的机制已经比工作线程更有效地处理它。

    这种说法的理由是什么?

    主线程和工作线程在I/O方面有什么区别?

    工人的目的不是不局限于非阻塞异步操作吗?

    在什么情况下,工作线程中的I/O性能可能会降低效率?

    0 回复  |  直到 7 年前
        1
  •  1
  •   Criminal_Affair_At_SO    4 年前

    您在Node中发现了一个明显的性能问题。js。

    我猜您是在非常大的文件上测试它,因为这是这个问题影响最大的地方。

    问题是 readFileSync 在一次操作中读取整个文件(一次 read 系统调用),而 readFile 读取512Kb的数据块。

    我已经提交了一份PR来解决这个问题,下面是讨论: https://github.com/nodejs/node/pull/41436

    用这个公关 读取文件 然后变得稍微快一点 readFileSync 没有 创建新线程的开销。如果添加新的线程创建,差异会更加明显。

    节点。js是为异步IO设计的,这是最有效的。

    推荐文章