超小的性能优化 nodejs脚本

108 阅读1分钟

我本身对node的api并不熟悉,多的是学习别人的代码。 一个深度获取目录的函数,是在同行的代码的借鉴过来的,也一直在用。

read_all_files = (path) => {
    var pa = fs.readdirSync(path);
    var files = [];
    pa.forEach((ele, index) => {
        let child = path + "/" + ele;
        let info = fs.statSync(child);
        if (info.isDirectory()) {
            let subs = read_all_files(child);
            subs.forEach((s) => files.push(s));
        } else {
            files.push(child);
        }
    });
    return files;
};

在学习的过程中,我也尝试重写他的代码,改成了下面这样的。但基本上变化不大。只是增加了入参的包容程度。

import { readdirSync, statSync, Stats } from "fs";

/**  迭代返回子级文件
 * @param path 读取目录
 * @returns 全部子文件清单
 */
export function read_all_files(path: string | ReadonlyArray<string>): string[] {
    /** 文件集处理 */
    let active: (fileStats: Stats) => ((context: string[], newfile: string) => number)
        = a => a.isDirectory()
            ? (b, c) => b.push.apply(b, read_all_files(c))
            : (b, c) => b.push(c);

    let files: string[] = [];
    if (typeof(path)=='string')
        readdirSync(path)
            .map(e => path + '/' + e)
            .forEach(child => active(statSync(child))(files, child));
    else
        files = path.map(read_all_files).flat()
    return files;
};

昨天在看一个老外的代码的时候,学到fs.readdirSync可以带参,加上这两年的开发经验,就尝试重做了这个深度遍历。

/** 深度获取目录 */
export function DeepRead(path: string | ReadonlyArray<string>): string[] {
    return [path]
        .flat()
        .map(dir => 
            readdirSync(dir, { withFileTypes: true })
                .map(e => {
                    if (e.isDirectory())
                        return DeepRead(`${dir}/${e.name}`)
                    return `${dir}/${e.name}`
                })
            )
        .flat(2)
}

我对一个 有将近5000个文件的目录进行了测试,测试结果也确实令我大吃一惊。居然有十倍的差距。

console.time('read_all_file')
read_all_file('maps')
console.timeEnd('read_all_file')

console.time('read_all_files')
read_all_files('maps')
console.timeEnd('read_all_files')

console.time('DeepRead')
DeepRead('maps')
console.timeEnd('DeepRead')

// read_all_file: 130.862ms
// read_all_files: 118.388ms
// DeepRead: 12.851ms

也有一些小测试 对于可能是数组也可能是字符串的参数,Array.isArray(path) ? path : [path]也不会比[path].flat()存在优势。 Array.flatMap也不是完全比Array.map().flat()存在优势,甚至可能会更慢。