摘要:創建多個對象同樣也會影響垃圾回收。譯注這里清除的是變量中存放的數據避免創建對象當然,降低垃圾回收最簡單的方式是不要去創建對象。并不存在無痛地有效刪除數組中某個對象的方法。
部分翻譯自原文地址
若你想讓你的游戲有60楨/秒的體驗,你必須要做的就是在16浩渺內完成所有事:子彈運動,創建實體,控制碰撞,軌跡,變換場景,控制輸入,播放音效。主流的游戲循環中,你需要做到盡可能高效。即便在30楨/秒的體驗中,你也只有32毫秒去完成這一切。特別是當你想要讓游戲更加豐滿時,速度與效率會顯得尤為重要。
垃圾回收究竟是什么?為何要關注垃圾回收?如果你開發的游戲在同一時間內發生了許多事,例如每秒發射5次導彈的武器(一把有著極高射速的非凡武器)。你很快就會發現原型構建及其后的垃圾回收將嚴重拖累性能。
當你的項目變得越來越復雜,在構建新事物時,你將會感受到明顯的延遲,特別是當你設置復雜場景與音效時(即便你已經緩存了靜態資源)。創建多個對象同樣也會影響垃圾回收。
像其他解釋型語言一樣JavaScript把你從內存管理中解放出來。你可以隨意創建對象而不用去考慮追蹤的問題。瀏覽器(實際上是運行在瀏覽器環境中的js虛擬器)將會周期性運行并清除你不用的代碼。這部分系統就是垃圾回收(garbage collector)簡稱GC,你可以把它想象為終極女傭。
有賴于瀏覽器,你使用的大量的對象可以在垃圾回收機制下在10到2000毫秒內被清除。該機制花費的時間取決于,究竟有多少代碼需要檢查,有多少對象需要清除。如果你在寫一個有許多獨立運行的對象的游戲,例如作戰類游戲。最好的情況是可察覺的卡頓,而最壞的情況則是大量的卡頓毀掉了體驗。
有好的垃圾回收代碼大多數情況有賴于垃圾回收機制,我們可以很輕易編寫代碼。唯一需要注意的就是不要應用那些你已經不需要使用的對象。例如下面的案例:
function test() { var myString = "a string"; } test();
在函數test執行之后,變量myString 將會被標記為閑置的等待釋放/刪除。因為函數創建了一個可聲明變量的作用域。在作用域中,瀏覽器會為開辟空間存放變量myString直到函數不再被使用,作用域中的一切都將被回收。在其后的某個時刻(由瀏覽器自行計算),GC將會執行,變量myString 會“真地”被移除內存得到釋放。
當然如果還有引用,GC將不會回收變量,如:
var another = null; function test() { var str = "A string I am"; another = str; } test();
在上例中,全局作用域中的另一個變量在函數內引用了str,因此垃圾回收器將不會回收str。
再看看別的例子,當你不適用var關鍵字時,js會將其理解為一個全局變量:
// var b = null; // 在外部聲明 function test() { var str = "A string I am"; b = str; // 沒有var 會被理解為全集變量 } test();如何真正地刪除變量?
那么問題來了,如何真實地了解到變量是否被刪除,即被垃圾回收器清理了?
var s = { data: "test" }; delete s.data;
首先,JavaScript提供了delete關鍵字,所以可以用它來實現?不幸的是,不能。delete是用來清除對象屬性的。顯然這是一個間接清除對對象/變量清除引用的方式,但這并沒有直接刪除變量。當你想要把一個對象的屬性變成undefined而非null時,該方法還是挺有用的:
var s = { data: "test" }; delete s.data;
s.data現在變為了undefined(同時也被垃圾回收器標記為“去除”)
當你使用同樣的方式用delete去刪除一個變量時將會失敗:
var m = "test"; delete m; // 默認返回 false (不允許操作) m === "test"; // true - oops, 依舊是那個值
delete很好用,但對于一個變量(這里指基本類型)則會失效。因此引用并不會被清除,內存也不會被垃圾回收器回收。使用delete將返回false來表示這個變量不會被刪除。
刪除變量真確的方式是:把變量設為null,之后垃圾回收器就會去做他該做的事。
var m = "test"; m = null; m === "test"; // false
該方法對屬性與對象同樣適用:
var s = { data: "test" }; s.data = null; // not required s = null; // 該操作同時也會清除s.data
其后數據將自動清除,因為沒有變量引用它了。
(譯注:這里清除的是變量中存放的數據)
當然,降低垃圾回收最簡單的方式是不要去創建對象。最直接的方式就是使用new關鍵字。
var newObject = new MyObject();
但是還有一些更簡潔的方法:
var a = []; // 創建一個數組 var t = { }; // 創建一個對象
需要記住的是function也會被當作對象處理:
function getCompare() { return function(a, b) { return a < b; } }
這段代碼在每次調用時都會生成一個新的(函數)對象。在JavaScript中由于函數是一個對象,所以垃圾回收器也能用同樣的方式處理。
另一種產生對象的方式是使用函數:
function getResult(} { return { result: true, value: "test" }; //調用時創建新的對象 }
最后,有一個藏得很深的方式:
var b = a.slice(1); // 創建一個新的完全復制的數組
Array.slice方法在每次調用時會創建一個新的對象/數組。并不存在無痛地有效刪除數組中某個對象的方法。誠然現在瀏覽器在這方面做了很多優化,但頻繁進行這樣的操作對性能仍是一種挑戰。(在Playcraft引擎采用雙向鏈表作為替代,詳見gamecore.js)
可控的垃圾回收即便你降低了你創建對象的數量,你依舊在消耗內存。你可以使用一個相當簡單的工具來了追蹤你消耗的內存即因而帶來的垃圾回收工作消耗的內存。
Chrome提供了一個觀測JavaScript堆(分配給JavaScript對象的內存)狀態的方式,你需要在命令行輸入一下代碼來保證其能夠運行:
chrome --enable-memory-info
如果你想要永久的使用這個工具,你可以這樣做:
do shell script ""/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --enable-memory-info"
保存這段腳本并將其作為你新的Chrome launcher。
一旦你啟動了Chrome 的內存分析,你可以訪問如下兩個屬性:
window.performance.memory.totalJSHeapSize; // 當前使用的堆內存 window.performance.memory.usedJSHeapSize; // 全部的堆內存
這兩個值表示當前有多少內存被分配給JavaScript,其中有多少被所有的變量/對象使用。如果你規律地輸出被使用的堆,你可以了解到你游戲的內存使用情況。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86601.html
摘要:這是因為我們訪問了數組中不存在的數組元素它超過了最后一個實際分配到內存的數組元素字節,并且有可能會讀取或者覆寫的位。包含個元素的新數組由和數組元素所組成中的內存使用中使用分配的內存主要指的是內存讀寫。 原文請查閱這里,本文有進行刪減,文后增了些經驗總結。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第三章。 我們將會討論日常使用中另一個被開發...
摘要:今天,就為開發者介紹個方便的工具。對開發者來說,是一個非常有用的工具,它提供了超過個有用的函數。該工具檢查輸入源代碼和報告任何違反給定的標準。框架是一個開發的工具。它側重于安全性和性能,絕對是最安全的開發框架之一。 PHP是為Web開發設計的服務器腳本語言,但也是一種通用的編程語言。超過2.4億個索引域使用PHP,包括很多重要的網站,例如Facebook、Digg和WordPress。...
摘要:表示允許垃圾收集線程處理本次垃圾收集開始前沒有處理好的日志緩沖區,這可以確保當前分區的是最新的。垃圾收集線程在完成其他任務的時間展示每個垃圾收集線程的最小最大平均差值和總共時間。 本文翻譯自:https://www.redhat.com/en/blog/collecting-and-reading-g1-garbage-collector-logs-part-2?source=auth...
閱讀 2001·2021-11-24 10:45
閱讀 1857·2021-10-09 09:43
閱讀 1296·2021-09-22 15:38
閱讀 1227·2021-08-18 10:19
閱讀 2840·2019-08-30 15:55
閱讀 3065·2019-08-30 12:45
閱讀 2967·2019-08-30 11:25
閱讀 361·2019-08-29 11:30