0

我有多个功能调用在一个链中的下一个,在处理相当大的数据集,以同样大组不同的数据:如何释放先前堆栈帧的存储器中的Javascript

function first_step(input_data, second_step_callback) 
{ 
    result = ... // do some processing 
    second_step_callback(result, third_step); 
} 

function second_step(intermediate_data, third_step_callback) 
{ 
    result = ... // do some processing 
    third_step_callback(result); 
} 

function third_step(intermediate_data) { } 

first_step(huge_data, second_step); 

third_step内存不足(当内存使用量达到大约1.5 GB时,Chrome似乎杀死了该选项卡)。

我认为,当达到third_step()时,input_datafirst_step()仍然保留,因为first_step()是在调用栈上,不是吗?至少在调试器运行时,我可以看到数据。

显然我不需要它了。在first_step()之后second_step_callback(result, third_step);之后没有代码。也许如果我可以释放内存,我的选项卡可能在处理这种大小的数据集时仍然存在。我可以这样做吗?

+1

1.5千兆字节比客户端代码中的*“相当大”*要多得多,你可以肯定你没有无限循环 – adeneo

+0

它在处理300 MB输入文件时发生(https:// github.com/AndreKR/XdebugFlamechartConverter)和似乎合理的内存使用情况。我无法真正把它分解成大块,因为在某些时候我必须把整棵树留在记忆中。这就是为什么我想在继续处理树进入下一步之前丢弃原始数据的原因。 – AndreKR

回答

1

没有看到更多你真正在做的事情是使用内存,我们很难判断你只是使用了太多的内存,还是只需要让更早的内存得到释放。

而且,Javascript中的内存不是由堆栈框架“拥有”,所以这个问题的前提似乎有点错误的假设。 Javascript中的内存是垃圾收集的,并且当没有活的,可达的代码仍然有对数据的引用并且在垃圾收集器下一次运行时(在JS空闲时间)将获得垃圾回收时,符合GC的条件。

也就是说,如果你有代码,使嵌套函数的连续通话喜欢你的问题表明,你可以通过做一些事情减少内存使用量,:持有

  1. 清除变量大数据(只需将它们设置为null)不再需要。
  2. 减少使用容纳大量数据的中间变量。
  3. 减少数据的复制。
  4. 减少带有中间结果的字符串操作,因为每个都会创建内存块,然后必须回收。
  5. 使用setTimeout()来清除堆栈,以运行链中的下一步,并允许垃圾收集器有机会在早期的临时变量上执行它的操作。
  6. 重构您处理或存储数据的方式,从根本上减少内存使用量。
+0

这似乎是我的问题(如何清除调用堆栈保留的内存),只有第5个数字是答案(它只能用'setTimeout()')。数字1似乎很有趣,但是如果我在'first_step()'中执行'input_data = undefined',函数参数的内存实际上是否会被释放? – AndreKR

+0

@AndreKR - 这些都是减少正在使用的并发内存量的技术。我想他们都与你的整体问题有关。 1)和5)是改善你的函数调用序列使用的方法。 – jfriend00

+0

@AndreKR - 当对象或字符串或数组在其他地方被使用时(比如在函数参数中),将某些东西设置为'null'对你来说没有多大帮助,因为该项目仍然不符合垃圾回收的条件。为了帮助你使用这种技术,你需要将不再使用的东西“零”出来,而且没有其他人可以引用数据,并确保垃圾收集器有机会运行。 – jfriend00