【问题标题】:How can I fix this memory leak in my NodeJS file manipulation application?如何在我的 NodeJS 文件操作应用程序中修复此内存泄漏?
【发布时间】:2020-08-15 17:31:38
【问题描述】:

我的应用程序在这个阶段的目的是获取一个输入文件并将常见的密码替换添加到给定的密码短语中。问题是它对一个可能很大的文件(1+GB 的文本)执行此操作,每行一个密码,然后通过writeStream 将生成的潜在替换列表附加回相同的输入文件。

例如,输入 5_passwords.txt 包含:

password
hello
chicken
bye
bobthebuilder

可能会产生这样的文件:

...
p@s$w0rd
h3ll0
ch1ck3n
8y3
b0bth3bu11d34
...

当使用大文件时,内存使用量也会增加,但据我了解应该保持不变。以下是Memory use: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100 / 100)}MB的实际控制台输出日志

开始时的内存使用: Memory use: 20MB(关于应用程序应该使用的内容)

10 秒后的内存使用情况: Memory use: 476MB(呃哦...)

30 秒后的内存使用情况: Memory use: 1159MB (LIKE WOAH)

以下是我的相关代码:

const commonReplacesments = {
    a : [
        '4',
        '@'
    ],
    b : [
        '8'
    ],
    c : [
        '(',
        '{',
        '[',
        '<'
    ],
    e : [
        '3'
    ],
    g : [
        '6',
        '9'
    ],
    i : [
        '1',
        '!',
        '|'
    ],
    l : [
        '1',
        '|',
        '7'
    ],
    o : [
        '0'
    ],
    p : [
        '9'
    ],
    r : [
        '4'
    ],
    s : [
        '$',
        '5'
    ],
    t : [
        '+',
        '7'
    ],
    x : [
        '%'
    ],
    z : [
        '2'
    ]
}

// word ... is the word to generate *some* possible manipulations on using the commonreplacements above
const replaceWord = async (word) => {
    let wordsWithReplacements = []
    for (let i = 0; i < word.length; i++) {
        let currentWord = word
        if (currentWord[i] in commonReplacesments) {
            for (let j = 0; j < commonReplacesments[currentWord[i]].length; j++) {
                let replacer = new RegExp(currentWord[i], 'g')
                currentWord = currentWord.replace(replacer, commonReplacesments[currentWord[i][j])
                wordsWithReplacements.push(currentWord)

                // Reset word
                currentWord = word

                console.log(
                    `[${Date.now()}] Memory use: ${Math.round(
                        process.memoryUsage().heapUsed / 1024 / 1024 * 100 / 100
                    )}MB`
                )
            }
        }
    }

    return wordsWithReplacements
}

// passFile ... Is the absolute file path to the password file being manipulated.
const addCommonReplacements = async (passFile) => {
    const readStream = fs.createReadStream(passFile)

    console.log('Adding common replacements to existing phrases in password list...')

    try {
        await util.promisify(stream.pipeline)(async function*() {
            for await (const password of readStream) {
                yield `${await (await replaceWord(`${password}`)).join('\n')}`
            }
        }, fs.createWriteStream(passFile, { flags: 'a' }))
    } catch (err) {
        Promise.reject(`ERROR: Failed to write common replacements to file...${err}`)
    }
}

如果有人能提供一些见解来帮助我解决这个问题,我将不胜感激:)

谢谢!

【问题讨论】:

    标签: node.js api file express io


    【解决方案1】:

    我无法启动您的代码,但我提出了这个简化版本,它看起来运行良好(即使结果中有一些 undefined 值,但这与替换功能有关我并没有真正研究过)。您可以利用 Node.js 的内部包 readline 为您解析流中的行。

    const addCommonReplacements = async passFile => {
        const readStream = fs.createReadStream(passFile)
        const writeStream = fs.createWriteStream('out.txt')
    
        var rl = readline.createInterface(readStream, writeStream)
    
        rl.on('line', function (password) {
            writeStream.write(`${replaceWord(password)}\n`)
        });
    }
    

    另外,我认为读取和写入同一个文件不是一个好主意!

    PS。我在文件上运行脚本,该文件有 65536 行,使用的最大内存为 27MB。

    【讨论】:

    • 我试试看。谢谢你的文章!但是,我想知道,为什么您认为读取和写入同一个文件不是一个好主意?
    • 这段代码实际上并没有写任何东西。还请注意,replaceWord 函数是异步的,并返回可能替换的 list,因此您不能直接将列表写入 writeStream
    • 另外,我很确定问题出在replaceWord 函数上,而不是addCommonReplacements 函数上,因为当我运行代码时没有进行替换,只是从文件中读取并附加未修改的内容回写流它没有内存泄漏。
    猜你喜欢
    • 1970-01-01
    • 2020-05-24
    • 2017-06-28
    • 2020-05-25
    • 2021-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    相关资源
    最近更新 更多