2012-11-29 38 views
8

考慮這段JavaScript代碼:分配一個新的字符串值是否需要收集垃圾?

var s = "Some string"; 
s = "More string"; 

將垃圾收集器(GC)已經工作,這種操作之後怎麼辦?

(我不知道我是否應該擔心試圖儘量減少GC暫停時指定字符串文字。)

E:我稍微覺得好笑的是,雖然我在我的問題,我需要明確說明爲了儘量減少GC,每個人都認爲我錯了。如果一個人真的必須知道具體的細節:我有一個JavaScript的遊戲 - 它在Chrome中運行良好,但在Firefox中有半頻繁的暫停,這似乎是由於GC。 (我甚至用Firefox的MemChaser擴展進行了檢查,並且這些暫停與垃圾回收完全吻合。)

+3

發愁的時候你有性能問題的垃圾收集器,並且只有那些真正嚴肅的人。對於幾乎所有常見頁面而言,這是您最擔心的問題。 – Pointy

+2

儘管我想知道答案(這就是爲什麼我沒有提及上下文的原因),但在這種特殊情況下,我試圖提高遊戲引擎的性能。這幾乎是您*需要擔心GC的典型案例。 – starwed

+2

實際上,瞭解GC如何在項目早期工作是很好的,這樣當你遇到問題時,最終不會因爲重要的重要因素而導致最終改變方式你在做事情。 –

回答

8

是的,字符串需要被垃圾收集,就像任何其他類型的動態分配的對象。是的,這是一個值得關注的問題,因爲在繁忙循環中粗心分配對象肯定會導致性能問題。

但是,字符串值是不可變的(不可改變的),大多數現代JavaScript實現使用「字符串實施」,即它們只存儲每個唯一字符串值的一個實例。這意味着如果你有這樣的東西...

var s1 = "abc", 
    s2 = "abc"; 

...只會分配一個「abc」實例。這僅適用於字符串值,而不適用於String對象。

幾件事情要記住:

  1. 功能類似於substringslice等,將分配每個函數調用(如果調用使用不同的參數)的新對象。

  2. 儘管兩個變量都指向內存中的相同數據,但GC循環運行時仍有兩個變量需要處理。擁有太多局部變量也會傷害到你,因爲它們中的每一個都需要由GC處理,從而增加開銷。

上編寫高性能JavaScript的一些進一步閱讀:

+0

感謝您的回答。 (當然,我在搜索時已經遇到了所有這三個鏈接!:)) – starwed

0

是的,垃圾收集器將有一個包含"Some string"的字符串對象來擺脫。而且,在回答你的問題時,該字符串分配將爲GC工作。

由於字符串是不可變的,並且使用了很多,所以JS引擎有一個相當有效的方式來處理它們。你不應該注意到從垃圾收集一些字符串的任何暫停。垃圾回收器在JavaScript編程的正常過程中一直都有工作要做。這就是它應該如何工作。

如果您正在觀察GC的暫停,我寧可懷疑它來自幾個字符串。發生更大的問題的可能性更大。要麼有成千上萬的對象需要GC或GC的一些非常複雜的任務。如果不研究整體代碼,我們無法真正推測這一點。

這不應該成爲一個問題,除非你正在做一些巨大的循環和處理數以萬計的對象。在這種情況下,可能需要更仔細地編程以最小化創建的中間對象的數量。但是,如果缺少該級別的對象,則應首先清除可靠的代碼,然後僅在某些事情向您顯示需要擔心的性能問題時優化性能。

0

是的,但除非你以循環方式循環播放數百萬次,否則它不會成爲你擔心的因素。

-2

要回答你的問題:「我想知道試圖儘量減少GC暫停時,我是否應該擔心指定字符串常量」:第

你真的不需要擔心這樣的事情就垃圾收集。

創建&銷燬大量Javascript對象或大量DOM元素時,GC只是一個問題。

+0

這是不正確的。字符串本身是不可變的。所以「Some String」字符串是JS內存中的某個對象,當GC不再有任何引用時,它必須被GC刪除。 – jfriend00

+0

你是對的,回答更新反映。 –

0

正如您已經注意到的,JavaScript不是JavaScript。它運行在不同的平臺上,因此會有不同的性能特點。因此,對於「這種手術之後GC有工作要做的事情」這個問題的確切答案是什麼?是:也許。如果腳本與您展示的腳本一樣短,那麼JIT編譯器可能會完全丟棄第一個字符串。但是在語言定義中沒有規定它必須是這種方式或其他方式。所以最終它就像JavaScript中經常出現的那樣:你必須嘗試一下。

更有趣的問題也許是:你如何避免垃圾收集。這是儘量減少新對象的分配。遊戲通常具有相當數量的對象,並且通常不會有新對象,直到舊對象未被使用。對於字符串來說,這可能會更難,因爲它們在JS中是不可變的。因此,儘可能嘗試用其他(可變)表示替換字符串。