【问题标题】:Node js 'readline' - Ineffective mark-compacts near heap limit Allocation failed节点 js 'readline' - 堆限制附近的无效标记压缩分配失败
【发布时间】:2019-07-01 19:29:30
【问题描述】:

她是我在代码中所做的

基本上是做网页抓取

我正在阅读一个包含大约 3500 个链接的文本文件,然后我正在阅读每个链接,过滤我想要的链接并请求获取状态代码、链接和页面标题(使用cheerio)。我减慢了进程具有异步迭代器结构,用于逐行读取以及使用 axios 和异步等待。一切正常,直到第 900 个链接我得到这个令人讨厌的致命错误 '致命错误:无效标记压缩接近堆限制分配失败 - JavaScript 堆内存不足'

我不知道这里发生了什么,这是网络服务器把我踢出去(看起来不像)还是我的代码写得不好并且 v8 引擎没有处理它?(更有可能)

这是我的代码,如果有人想尝试使用大量链接运行,我使用https://hackertarget.com/extract-links/ 获取链接,然后将其放入文本文件中。

var request = require('request');
var cheerio = require('cheerio');
var URL = require('url-parse');
var axios = require('axios');
const fs = require('fs');
const readline = require('readline');
const timeout = require('./timeout')

var main = [];
async function processLineByLine() {
  const rl = readline.createInterface({
    input: fs.createReadStream('C:/Users/T440/Documents/crawl/links.txt'),
    crlfDelay: Infinity
  });

  for await (const line of rl) {
    if (line.startsWith('https://www.example.com')) {
      var encodeLink = encodeURI(line);
    
      const response =  await axios.get(encodeLink).catch((err)=>{
        var Status_ErrorsCatchaxios = {
            "status Code": err.response.status ?error.response.status:"No status code available",
            "Page title:": $('title').text()?$('title').text():'No title avaialble',
            "Original Link": encodeLink?encodeLink:"No Original Link Available",
            "errorCode":err
          }
          main.push(Status_ErrorsCatchaxios)
      })
      try {
        const body = response.data;
        if (response.status === 200) {
          // Parse the document body
          var $ = cheerio.load(body);
          var Status_200 = {
            "status Code": response.status,
            "Page title:": $('title').text(),
            "Original Link": encodeLink,
          }
          main.push(Status_200)
        }
  
        if (response.status === 302 || response.status === 404 || response.status === 500) {
          // Parse the document body
          var Status_Errors = {
            "status Code": response.status,
            "Page title:": $('title').text(),
            "Original Link": encodeLink,
          }
          main.push(Status_Errors)
        }
            fs.writeFile("C:/Users/T440/Documents/crawl/output.json", JSON.stringify(main), (err) => {
            if (err) console.log(err);
            console.log("Successfully Written to File.");
          });
      } catch (error) {

          var Status_ErrorsCatch = {
          "status Code": response.status ?error.response.status:"No status code available",
          "Page title:": $('title').text()?$('title').text():'No title avaialble',
          "Original Link": encodeLink?encodeLink:"No Original Link Available",
        }
        main.push(Status_ErrorsCatch)
      }      
        
    }
  }
}
processLineByLine()

【问题讨论】:

  • 我也有同样的问题,你能解决吗?

标签: javascript node.js express httprequest v8


【解决方案1】:

我相信我遇到了同样的问题。最初发现这个问题的参考:cheerio+v8 "leaks" memory。我认为这是 Cheerio/V8 中的内存泄漏。我还没有找到解决问题的方法,但我尝试了以下方法:

  1. 创建一个 Unleak 函数,如下所示:Unleak
  2. 运行具有更多内存的节点 'node --max-old-space-size=8192 app.js'
  3. 在垃圾收集器暴露的情况下运行节点并将其命名为“node -expose-gc app.js”调用 Global.gc()

1 和 2 的效果最大。我确定这只是我的代码,因为这是老问题。

【讨论】:

    【解决方案2】:

    2022 年更新

    我必须阅读一个文本文件,其中包含逐行存储的 2 亿多个域。有了这么多数据,你可以想象 Node 和我的笔记本电脑是如何被吓坏的。

    所以,我想提供一个不涉及增加内存大小或任何类似疯狂的解决方案。 Cheerio、readline 和 v8 存在一个已知的内存泄漏问题。达到一定限制后,您的 Node 服务器将自毁并终止所有进程。增加内存大小可能有效,也可能无效。就我而言,它不起作用。事实上,在增加内存之后,它比以前更糟糕,并且崩溃得更早。

    TLDR;

    如果您想阅读超大文件(数千或数百万行)逐行,您可以使用库event-stream 来完成。其他一切对我来说都失败了,我尝试了许多不同的解决方案。

    //event-stream
    const es = require('event-stream');//npm i event-stream
    
    //timestamp
    const timestamp= Math.floor(new Date() / 1000);
     
    //declare array
    var domains = [];
    
    //get line count for file
    var lineCount = 0;
    
    //stream
    var s = fs
    .createReadStream('domains.txt')//your extremely large file goes here Jedi you
    .pipe(es.split())
    .pipe(
    es
    .mapSync(function(line) {
    
    //count line
    lineCount++;
    var count = lineCount++;
    
    //domain
    var domain = {
    id : count,
    timestamp : timestamp,
    domain : line,
    }
    
    //push domains to json array collection
    domains.push(domain);
    
    //console.time('line count');
    console.log(domain);
    
    })
    .on('error', function(err) {
    console.log('Error while reading file.', err);
    })
    .on('end', function() {
    
    //done
    console.log('Read entire file.');
    
    //print total lines
    console.log(lineCount);
    console.timeEnd('line count');
    
    //print json array to do whatever
    console.log(domains);
    }),
    );
    

    【讨论】:

      猜你喜欢
      • 2021-06-10
      • 2019-10-29
      • 2021-12-01
      • 1970-01-01
      • 2020-05-14
      • 1970-01-01
      • 2022-10-06
      • 2019-10-14
      • 2020-03-12
      相关资源
      最近更新 更多