簡體   English   中英

可以將對象標記為不被垃圾收集嗎?

[英]can objects be marked not to be garbage collected?

我不太了解JavaScript垃圾收集器,只是它試圖管理引用,以便可以定期從內存中清除未引用的對象。 如果語言實施者可行的話,我正在思考一些我認為可以提高性能的東西。

它會像這樣。 在文件中添加一行:

"no gc";

這類似於use strict設置。 它會將文件中定義的所有內容標記為不進行垃圾回收。 我認為這將在jQuery和下划線等庫中使用。 所有輔助方法都將被標記並存儲在不由GC管理的單獨的內存區域中。

雖然我知道這可能最終會保留那些從未使用過的東西; 它至少會將它與定期的GC過程隔離開來。 因此,雖然我們可能會吞噬一些額外的內存,但至少可以減輕GC處理的負擔。

我為這個建議的天真而道歉,因為我從未實施過GC。 我只是想知道這個想法是否可行,或者JavaScript是否已經以某種方式做到了這一點。

如果你想將它們保存為緩存,那么你就擁有了全局范圍。

在瀏覽器中全局范圍是窗口,

因此,如果您不希望對象X永遠不會被垃圾收集,那么您只需編寫即可

window.nogc = X;

因為全局范圍的窗口,將永遠不會被垃圾收集,所以它的子引用也不會被垃圾收集,直到我們明確地實現它。

垃圾收集僅在線程空閑時運行。 沒有任何內容可以保存,因為GC僅在系統不忙時才會發生。

所以不,這是不可能的。

您可以通過從GC根目錄引用它來確保不收集對象,但不能確保它不會被GC處理。

原因是JS VM中的GC通常通過Mark-and-Sweep或功能相同的方法實現。 基本前提是GC經歷了這樣一個循環:

  1. GC將堆中的所有對象標記為“可能可用於釋放”。 這通常通過標志切換來完成,該標志切換改變對象上現有標記的解釋 ,從“需要保持”到“安全釋放”。 因此,在此階段不會對對象進行實際迭代。 告訴GC“不標記”某些對象實際上需要額外的操作,而不是更少。

  2. GC從GC根開始,遍歷參考樹,將對象標記從“安全釋放”更改為“需要保留”。 這是“馬克”階段。 GC根可以是全局對象,當前正在執行的堆棧,事件循環上的掛起回調等。樹遍歷本身也可以以各種方式完成,DFS是最簡單的。

  3. GC遍歷堆中的所有對象,並刪除任何仍標記為“可安全釋放”的對象。 這是“掃盪”階段。 此階段存在許多優化,這允許GC在單個操作中釋放一組對象使用的內存。 然而,這需要至少某種程度的迭代,而不是對象組,如果不是對象本身。

現在這里是設置“非GC”競技場的問題:假設“非GC”競技場中的對象是引用常規對象。 在“標記”階段,如果未標記該對象,則將釋放該對象。 這意味着所有“不可收集”的對象都需要是GC根,以便“保留”它們所引用的常規對象。 作為GC根目錄,與GC根目錄直接引用相比,沒有任何性能優勢。 兩者都必須平等地參與“馬克”階段。

唯一的選擇是您的不可收集的對象根本無法強烈引用可收集的對象。 這可以通過擁有自己的二進制堆而不是使用本機JS對象來實現。 二進制數據不會被解釋為引用,並且堆對象將在單個操作中完成其標記階段。 這就是asm.js的作用:它預先分配一個大型數組作為其內部堆。 對於VM,整個數組都算作一個大對象,因此不會對在其中編碼的任何數據結構進行垃圾回收。 使用此方法確實存在將所有對象和數據結構編碼為堆的二進制格式所需的缺陷,並在您想要使用它們時對其進行解碼。 使用asm.js時,這由編譯器處理。

在JavaScript中,如果要殺死對象,則必須刪除所有引用。 假設我們有一個像這樣的對象:

var myobj={ obj : {} };

我們想要GC的obj對象,我們必須這樣做:

myobj["obj"] = null;
delete myobj["obj"];

但如果你定義另一個引用該對象的變量,它將不會被這些行殺死。 例如,如果你這樣做:

var obj = myobj.obj;

如果您確實要刪除該對象,則對此變量執行相同操作:

obj  = null;
delete obj;

然后,如果沒有參考,它將被殺死。 換句話說,如果你想阻止你的對象從GC,在某個地方創建一個引用並保持私有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM