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