V2EX 首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Node.js
Express
PPA for Ubuntu
ppa:chris-lea/node.js
V2EX  ›  Node.js

nodejs, 多 IO 操作,如何提高执行效率??

  •  
  •   actto · 66 天前 · 1043 次点击
    这是一个创建于 66 天前的主题,其中的信息可能已经有所发展或是发生改变。

    主要操作:(文件去重)

    function files_do(){
        let MD5 = 读(buffer 生成 MD5);
        if(从数据库找相同 MD5 的值.Count()==0){
           //没找到
           数据库.insert(文件信息);
        }else{
           //有相同值
           文件移动(原路径, 目标路径);
        }
        setTimeout(function(){
        	files_do()
        },0)
    }
    

    目前 5 万个文件(大小: 几 k 到十几 M 都有), 大概需要 6 个小时多..

    需要处理几百万个文件.

    有什么办法能进一步提高执行效率??

    15 回复  |  直到 2017-04-22 14:19:20 +08:00
        1
    TJT   66 天前   ♥ 1
    先分析性能消耗在哪里。可能的优化方法有数据库所有的 MD5 放到 Set 里面,这样就直接干掉数据库了、多线程 /多进程、用 C 重写。
        2
    crayygy   66 天前 via iPhone   ♥ 1
    粗略的想了一下,主要的消耗有两个,一是读文件, IO 消耗比较大,二是数据库查询,消耗也不小。第一个没办法,如果你对内容要求不多,直接对整个文件做校验或许就可以了。数据库的话就像楼上说的,几万个也不多,直接存在内存里,然后统一写数据库。
        3
    XiaoxiaoPu   66 天前   ♥ 1
    不要直接比较 md5 ,先比较文件长度,再比较文件的部分内容(比如开头 1 KiB ),最后比较 md5 。
        4
    keller   66 天前   ♥ 1
    不要直接对比 md5 先对比文件大小 相同大小的文件再做 md5 对比
        5
    actto   66 天前
    谢谢大家!!!
    1, 我目前就用的内存数据库, 定期写回 db 文件里..所以目前数据库查询效率还可以.
    2, "先比较文件大小" 不可行..因为 db.insert(文件信息) 必须有 MD5 值(因为后面的文件需要和它比对)....也还是得读一遍文件 buffer...
    3, 现在考虑用 C++写 多线程读 buffer,并生成 MD5 的操作..先写入数据库..全部结束后, 数据库查重复, 再移动文件.
        6
    lldld   66 天前 via iPhone
    @actto 楼上
    @XiaoxiaoPu 的建议不错。
    读文件的时候不要读整个文件求 md5.

    可以分三步:
    1) 按照文件大小和文件前 256bytes 的 md5 来确定可能会重复的文件
    2) 对 1 的结果求整个文件的 md5, 确定重复的文件
    3) 去重
        7
    coderfox   66 天前 via Android
    读 buffer 生成 MD5 可以换成调用 md5 终端指令。也许能改善,取决于 node 的 md5 实现如何。
        8
    breeswish   66 天前
    md5 没啥性能瓶颈的,一般单核每秒都有几百兆。楼主需要先看一下 node CPU 是否跑满单核了,按照楼主 po 的代码来看是有异步性能浪费的( setTimeout ),当然实际代码也许不是长成这样。如果单核已经跑满了,可以考虑上多个进程并行运行。
    优化的上线应当接近于这 5 万个文件全部读取一遍的性能。
        9
    breeswish   66 天前
    另外楼主可以考虑直接将文件流 pipe 到 hash ,可以避免频繁的 buffer alloc ,进一步压榨一些性能。
    用 C++ 生成 md5 就不用想了, nodejs 人家不是用 js 算的 md5 ,是 openssl 计算的,自己写的效率一般不会更高。
        10
    breeswish   66 天前
    当然上面说的那些的前提是不频繁访问数据库。数据库一般是个瓶颈,一楼已经给出优化数据库的方法了。
    不过不建议用 C 重写 :P 这个需求的终极瓶颈理论上在 IO ,如果测下来瓶颈不在 IO 上那么就是可以优化的。以及既然终极瓶颈是 IO ,那么我猜测不用异步写 C 的话会写得单核性能比 nodejs 版还要低。
        11
    actto   66 天前 via Android
    @breeswish 谢谢给出的建议!!!
    我的代码确实有用到 setTimeout ,因为希望页面上能反应出进度,给 dom 操作留点时间。(electron 小程序,数据库用的 LokiJS)
    整体代码就是递归循环整个文件夹,找到所有的文件去重。重复文件放在固定文件夹,等待人工检查。
    cpu 目前占用 20%不到(18%— 19%左右)。
        12
    guokeke   66 天前
    @breeswish 你玩 telegram 吗?喵?
        13
    breeswish   65 天前
    @guokeke breezewish
        14
    breeswish   65 天前
    @actto 这么来说目测你的 IO 用的也都是同步的 IO 了……?那么你首先要做的是全改成异步的 IO ,然后用上一些异步流程控制的库比如 caolan/async 来进行控制(比如可以用上它的 queue )。然后 setTimeout 可以去掉了
        15
    qfdk   65 天前 via iPhone
    你把文件合并一下 大体看看读取 500m 是个啥速度 按道理 应该不慢 另外读取文件有异步和同步两种方式
    DigitalOcean
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   鸣谢   ·   2485 人在线   最高记录 2607   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.7.5 · 49ms · UTC 02:02 · PVG 10:02 · LAX 19:02 · JFK 22:02
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1