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