在 Node.js 同步/异步性能和速度中移动 100.000 多个文件 [关闭]

Posted

技术标签:

【中文标题】在 Node.js 同步/异步性能和速度中移动 100.000 多个文件 [关闭]【英文标题】:Moving 100.000+ files in Node.js sync / async performance and speed [closed] 【发布时间】:2017-10-12 14:55:54 【问题描述】:

我正在尝试找出最快的方法,同时使用 Node.js 同步或异步移动 100.000 多个文件时不会对性能产生太大影响

我使用 3 个不同的循环 forEach async.eachfor 进行了同步和异步测试。循环迭代对时序结果的影响不大。影响性能和速度的最大逻辑是同步或异步移动文件。

测试用例显示,同步 renameSync() 比异步 rename() 慢 20%。同时异步 rename() 使用 3 倍的 CPU 功率,然后是同步 renameSync()


我是否正确假设使用同步 renameSync() 会更明智,因为异步 rename() 中的速度提升并不那么显着,等于 20%。虽然异步版本中的 CPU 使用开销似乎很大 - 300%?

还是我错过了什么?也许在速度/性能方面有更好的解决方法。

时间安排:

eachAsyncRenameAsync()

node rename.js  1.60s user 11.20s system 280% cpu 4.559 total
node rename.js  1.65s user 11.82s system 284% cpu 4.732 total
node rename.js  1.64s user 11.84s system 292% cpu 4.606 total


eachSyncRenameSync()

node rename.js  0.69s user 5.01s system 97% cpu 5.851 total
node rename.js  0.67s user 4.88s system 97% cpu 5.687 total
node rename.js  0.68s user 5.01s system 99% cpu 5.734 total


eachAsyncRenameSync()

node rename.js  0.67s user 4.99s system 97% cpu 5.797 total
node rename.js  0.68s user 4.95s system 97% cpu 5.754 total
node rename.js  0.66s user 4.89s system 97% cpu 5.690 total


eachSyncRenameAsync()

node rename.js  1.63s user 11.12s system 274% cpu 4.638 total
node rename.js  1.66s user 12.29s system 286% cpu 4.874 total
node rename.js  1.66s user 12.23s system 289% cpu 4.795 total


forSyncRenameAsync()

node rename.js  1.72s user 12.04s system 283% cpu 4.862 total
node rename.js  1.69s user 11.88s system 276% cpu 4.904 total
node rename.js  1.64s user 11.89s system 287% cpu 4.712 total


forSyncRenameSync()

node rename.js  0.64s user 4.94s system 97% cpu 5.715 total
node rename.js  0.66s user 5.01s system 97% cpu 5.807 total
node rename.js  0.65s user 4.93s system 99% cpu 5.616 total

代码:

const fs = require('fs')
const path = require('path')
const  each  = require('async')

let dir = '/opt/bin/test/Random 100000'
let dir2 = '/opt/bin/test/Random 100000 2'

function eachAsyncRenameAsync(files) 
        each(files, file => 
              fs.rename(path.join(dir,file), path.join(dir2,file), err => 
                if(err)  console.log(err) 
              )
        )


function eachSyncRenameSync(files) 
    files.forEach(file => 
            fs.renameSync(path.join(dir,file), path.join(dir2,file))
    )


function eachAsyncRenameSync(files) 
    each(files, file => 
            fs.renameSync(path.join(dir,file), path.join(dir2,file))
    )


function eachSyncRenameAsync(files) 
    files.forEach(file => 
        fs.rename(path.join(dir,file), path.join(dir2,file), err => 
                if(err)  console.log(err) 
        )
    )


function forSyncRenameAsync(files) 
    for (i=0; i<files.length; i++) 
        fs.rename(path.join(dir, files[i]), path.join(dir2, files[i]), err => 
                if(err)  console.log(err) 
        )
    



function forSyncRenameSync(files) 
    for (i=0; i<files.length; i++) 
        fs.renameSync(path.join(dir, files[i]), path.join(dir2, files[i]))
    


// Reading dir asynchronously and moving files

fs.readdir(dir, (err, files) => 
    if (err)  console.log(err) 
    else 
        console.log('eachAsyncRenameAsync()')
        eachAsyncRenameAsync(files)
    
)

【问题讨论】:

【参考方案1】:

对于异步性能比较优化,创建一个池来限制并发操作的数量会让你找到最优的结果。

您所做的基准测试表明,最佳结果在 1 到 n 个异步并发操作之间。

【讨论】:

我不认为这里是解释数学理论的地方...我的答案需要对那些不熟悉数学的人进行更多解释...我不认为这种解释是我应该在这里做什么......仍然,使用池来处理过度使用异步回调,并对工作进行最佳优化,将产生最好的结果。这里,n 是异步并发操作的数量。对于已经处理回调的 nodejs 程序员来说,我的回答已经足够清楚了。 ----这如何回答OP的问题?---它没有解决它。这是替补席结果的解释。你会期待什么?生成一个池库作为以最佳方式完成整个工作的答案? ---- 其他评论者不见了,只是留下那些 cmets 让别人不要重复这种行为。谢谢。 “这是对替补结果的解释”——但它也没有解释任何事情。 @user2357112supportsMonica ,你为什么不让运维看到解决方案,虽然这是一个老问题,但问题是一般情况,我们许多nodejs开发人员都面临。这,你试图做的就是如此令人反感。使用池化方法,已经在 NodeJS 的官方文档中提出。该实现是最佳的,仅针对目标平台,使用池化并不困难。我写的答案显然对任何人都有帮助,对我来说是一个解决方案,如果你愿意,它将成为许多人的解决方案。

以上是关于在 Node.js 同步/异步性能和速度中移动 100.000 多个文件 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

同步和异步编程有啥区别(在node.js中)

nodejs进程线程优化性能

node.js同步及异步读取写入删除文件1

同步和异步 以及node js 回调函数

Node js中Promise是同步还是异步

返回异步数据,然后在 Node.js 中同步导出