V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
okface
V2EX  ›  Node.js

读取 15075 行数据的时候栈溢出?

  •  
  •   okface · 2018-01-16 19:36:49 +08:00 · 3905 次点击
    这是一个创建于 2503 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一共两万多行数据,我用二分法发现在读取 15075 行数据的时候就会报栈溢出,但是这行数据并没有什么不同。代码如下:
    中间的逻辑判断部分比较复杂?大佬无视就好。主要看我的递归哪里错了?

    function getdata(line)
    {
    i++;
    if (typeof line =='string'){//判断是否为字符串
    var dataarray = line.split(',');
    if (person.hasOwnProperty(dataarray[4]+dataarray[7]) == false){//判断是否字符串已存在,key 为 brand+x
    person[dataarray[4]+dataarray[7]] = dataarray;

    k ++;
    }
    else{//如果已存在

    if (real_length(String(dataarray)) > real_length(String(person[dataarray[4]+dataarray[7]]))){//比较字符串的非空长度,后者比前者大则替代

    l++;
    fWriteError.write(person[dataarray[4]+dataarray[7]]+os.EOL)//将淘汰的字符串记录下来
    person[dataarray[4]+dataarray[7]] = dataarray;


    }
    else if(real_length(String(dataarray)) == real_length(String(person[dataarray[4]+dataarray[7]]))){//比较字符串的非空长度,如果两者相等
    if (jmz.GetLength(String(dataarray[6])) > jmz.GetLength(String(person[dataarray[4]+dataarray[7]][6])) ){//比较字符串中 addr 字段的字符数
    console.log(dataarray[6]);
    console.log(person[dataarray[4]+dataarray[7]][6]);
    person[dataarray[4]+dataarray[7]] = dataarray;
    l++;
    }
    else{
    l++
    }

    }
    else{
    l++;
    }
    }
    }
    if(i<15705)
    {
    getdata(dataArrayAll[i])
    }
    }
    getdata(dataArrayAll[0]);
    5 条回复    2018-02-05 12:36:45 +08:00
    okface
        1
    okface  
    OP
       2018-01-16 19:39:16 +08:00
    不会整理代码。。各位放到格式化工具里看一下吧。。。
    semut
        2
    semut  
       2018-01-16 19:40:54 +08:00
    不懂 js,但是这个排版可以调整下,看着真难受
    feverzsj
        3
    feverzsj  
       2018-01-16 19:47:59 +08:00
    v8 现在应该可以自动去除尾递归的,可能是你的 node 版本太老了,不行就改成迭代好了
    okface
        4
    okface  
    OP
       2018-01-16 20:01:34 +08:00
    mdluo
        5
    mdluo  
       2018-02-05 12:36:45 +08:00   ❤️ 1
    1. 能用循环做的事情就不要用递归,递归相比循环有相当大的性能差距。

    2. node.js 只有特定几个版本有尾递归优化,而且需要 flag 来开启,最新版本是没有的( http://node.green/),函数调用的 Maximum call stack size 就是一个一万多的值。另外,ES6 里的尾递归优化是需要有 return 才可以的。

    2. 大文件读取尽量用 Stream,可以指定分块的长度,而且不会一直阻塞 event loop.

    3. 如果一定要用递归才能实现的逻辑,通过 setTimeout(func, 0)、setImmediate(func)、或者 process.nextTick(func) 把把递归的深度从 call stack 转移到 task queue.

    4. 另外代码优化相关的,能在循环外通过局部变量存起来的值就不用在循环里用函数调用去读取。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2200 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:34 · PVG 09:34 · LAX 17:34 · JFK 20:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.