久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

編寫高性能JavaScript

瀏覽:112日期:2023-11-22 08:50:05

很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是專門為需要快速執行的大型JavaScript應用所設計的。如果你是一個開發者,并且關心內存使用情況與頁面性能,你應該了解用戶瀏覽器中的JavaScript引擎是如何運作的。無論是V8,SpiderMonkey的(Firefox)的Carakan(Opera),Chakra(IE)或其他引擎,這樣做可以幫助你更好地優化你的應用程序。這并不是說應該專門為某一瀏覽器或引擎做優化,千萬別這么做。

但是,你應該問自己幾個問題:

在我的代碼里,是否可以使代碼更高效一些主流的JavaScript引擎都做了哪些優化什么是引擎無法優化的,垃圾回收器(GC)是否能回收我所期望的東西

編寫高性能JavaScript

加載快速的網站就像是一輛快速的跑車,需要用到特別定制的零件. 圖片來源: dHybridcars.

編寫高性能代碼時有一些常見的陷阱,在這篇文章中,我們將展示一些經過驗證的、更好的編寫代碼方式。

那么,JavaScript在V8里是如何工作的?

如果你對JS引擎沒有較深的了解,開發一個大型Web應用也沒啥問題,就好比會開車的人也只是看過引擎蓋而沒有看過車蓋內的引擎一樣。鑒于Chrome是我的瀏覽器首選,所以談一下它的JavaScript引擎。V8是由以下幾個核心部分組成:

一個基本的編譯器,它會在代碼執行前解析JavaScript代碼并生成本地機器碼,而不是執行字節碼或簡單地解釋它。這些代碼最開始并不是高度優化的。V8將對象構建為對象模型。在JavaScript中對象表現為關聯數組,但是在V8中對象被看作是隱藏的類,一個為了優化查詢的內部類型系統。運行時分析器監視正在運行的系統,并標識了“hot”的函數(例如花費很長時間運行的代碼)。優化編譯器重新編譯和優化那些被運行時分析器標識為“hot”的代碼,并進行“內聯”等優化(例如用被調用者的主體替換函數調用的位置)。V8支持去優化,這意味著優化編譯器如果發現對于代碼優化的假設過于樂觀,它會舍棄優化過的代碼。V8有個垃圾收集器,了解它是如何工作的和優化JavaScript一樣重要。

垃圾回收

垃圾回收是內存管理的一種形式,其實就是一個收集器的概念,嘗試回收不再被使用的對象所占用的內存。在JavaScript這種垃圾回收語言中,應用程序中仍在被引用的對象不會被清除。

手動消除對象引用在大多數情況下是沒有必要的。通過簡單地把變量放在需要它們的地方(理想情況下,盡可能是局部作用域,即它們被使用的函數里而不是函數外層),一切將運作地很好。

編寫高性能JavaScript

  垃圾回收器嘗試回收內存. 圖片來源: Valtteri Mäki.

在JavaScript中,是不可能強制進行垃圾回收的。你不應該這么做,因為垃圾收集過程是由運行時控制的,它知道什么是最好的清理時機。

“消除引用”的誤解

網上有許多關于JavaScript內存回收的討論都談到delete這個關鍵字,雖然它可以被用來刪除對象(map)中的屬性(key),但有部分開發者認為它可以用來強制“消除引用”。建議盡可能避免使用delete,在下面的例子中delete o.x 的弊大于利,因為它改變了o的隱藏類,并使它成為一個"慢對象"。

var o = { x: 1 };delete o.x; // trueo.x; // undefined

你會很容易地在流行的JS庫中找到引用刪除——這是具有語言目的性的。這里需要注意的是避免在運行時修改”hot”對象的結構。JavaScript引擎可以檢測出這種“hot”的對象,并嘗試對其進行優化。如果對象在生命周期中其結構沒有較大的改變,引擎將會更容易優化對象,而delete操作實際上會觸發這種較大的結構改變,因此不利于引擎的優化。

對于null是如何工作也是有誤解的。將一個對象引用設置為null,并沒有使對象變“空”,只是將它的引用設置為空而已。使用o.x= null比使用delete會更好些,但可能也不是很必要。

var o = { x: 1 };o = null;o; // nullo.x // TypeError

如果此引用是當前對象的最后引用,那么該對象將被作為垃圾回收。如果此引用不是當前對象的最后引用,則該對象是可訪問的且不會被垃圾回收。

另外需要注意的是,全局變量在頁面的生命周期里是不被垃圾回收器清理的。無論頁面打開多久,JavaScript運行時全局對象作用域中的變量會一直存在。

var myGlobalNamespace = {};

全局對象只會在刷新頁面、導航到其他頁面、關閉標簽頁或退出瀏覽器時才會被清理。函數作用域的變量將在超出作用域時被清理,即退出函數時,已經沒有任何引用,這樣的變量就被清理了。

經驗法則

為了使垃圾回收器盡早收集盡可能多的對象,不要hold著不再使用的對象。這里有幾件事需要記住:

正如前面提到的,在合適的范圍內使用變量是手動消除引用的更好選擇。即一個變量只在一個函數作用域中使用,就不要在全局作用域聲明它。這意味著更干凈省心的代碼。確保解綁那些不再需要的事件監聽器,尤其是那些即將被銷毀的DOM對象所綁定的事件監聽器。如果使用的數據緩存在本地,確保清理一下緩存或使用老化機制,以避免大量不被重用的數據被存儲。

函數

接下來,我們談談函數。正如我們已經說過,垃圾收集的工作原理,是通過回收不再是訪問的內存塊(對象)。為了更好地說明這一點,這里有一些例子。

function foo() { var bar = new LargeObject(); bar.someCall();}

當foo返回時,bar指向的對象將會被垃圾收集器自動回收,因為它已沒有任何存在的引用了。

對比一下:

function foo() { var bar = new LargeObject(); bar.someCall(); return bar;}// somewhere elsevar b = foo();

現在我們有一個引用指向bar對象,這樣bar對象的生存周期就從foo的調用一直持續到調用者指定別的變量b(或b超出范圍)。

閉包(CLOSURES)

當你看到一個函數,返回一個內部函數,該內部函數將獲得范圍外的訪問權,即使在外部函數執行之后。這是一個基本的閉包 —— 可以在特定的上下文中設置的變量的表達式。例如:

function sum (x) { function sumIt(y) {return x + y; }; return sumIt;}// Usagevar sumA = sum(4);var sumB = sumA(3);console.log(sumB); // Returns 7

在sum調用上下文中生成的函數對象(sumIt)是無法被回收的,它被全局變量(sumA)所引用,并且可以通過sumA(n)調用。

讓我們來看看另外一個例子,這里我們可以訪問變量largeStr嗎?

var a = function () { var largeStr = new Array(1000000).join('x'); return function () {return largeStr; };}();

是的,我們可以通過a()訪問largeStr,所以它沒有被回收。下面這個呢?

var a = function () { var smallStr = 'x'; var largeStr = new Array(1000000).join('x'); return function (n) {return smallStr; };}();

我們不能再訪問largeStr了,它已經是垃圾回收候選人了。【譯者注:因為largeStr已不存在外部引用了】

定時器

最糟的內存泄漏地方之一是在循環中,或者在setTimeout()/ setInterval()中,但這是相當常見的。思考下面的例子:

var myObj = { callMeMaybe: function () {var myRef = this;var val = setTimeout(function () { console.log('Time is running out!'); myRef.callMeMaybe();}, 1000); }};

如果我們運行myObj.callMeMaybe();來啟動定時器,可以看到控制臺每秒打印出“Time is running out!”。如果接著運行myObj = null,定時器依舊處于激活狀態。為了能夠持續執行,閉包將myObj傳遞給setTimeout,這樣myObj是無法被回收的。相反,它引用到myObj的因為它捕獲了myRef。這跟我們為了保持引用將閉包傳給其他的函數是一樣的。

同樣值得牢記的是,setTimeout/setInterval調用(如函數)中的引用,將需要執行和完成,才可以被垃圾收集。

當心性能陷阱

永遠不要優化代碼,直到你真正需要。現在經常可以看到一些基準測試,顯示N比M在V8中更為優化,但是在模塊代碼或應用中測試一下會發現,這些優化真正的效果比你期望的要小的多。

編寫高性能JavaScript

做的過多還不如什么都不做. 圖片來源: Tim Sheerman-Chase.

比如我們想要創建這樣一個模塊:

需要一個本地的數據源包含數字ID繪制包含這些數據的表格添加事件處理程序,當用戶點擊的任何單元格時切換單元格的css class

這個問題有幾個不同的因素,雖然也很容易解決。我們如何存儲數據,如何高效地繪制表格并且append到DOM中,如何更優地處理表格事件?

面對這些問題最開始(天真)的做法是使用對象存儲數據并放入數組中,使用jQuery遍歷數據繪制表格并append到DOM中,最后使用事件綁定我們期望地點擊行為。

注意:這不是你應該做的

var moduleA = function () { return {data: dataArrayObject,init: function () { this.addTable(); this.addEvents();},addTable: function () { for (var i = 0; i < rows; i++) {$tr = $('<tr></tr>');for (var j = 0; j < this.data.length; j++) { $tr.append('<td>' + this.data[j]['id'] + '</td>');}$tr.appendTo($tbody); }},addEvents: function () { $('table td').on('click', function () {$(this).toggleClass('active'); });} };}();

這段代碼簡單有效地完成了任務。

但在這種情況下,我們遍歷的數據只是本應該簡單地存放在數組中的數字型屬性ID。有趣的是,直接使用DocumentFragment和本地DOM方法比使用jQuery(以這種方式)來生成表格是更優的選擇,當然,事件代理比單獨綁定每個td具有更高的性能。

要注意雖然jQuery在內部使用DocumentFragment,但是在我們的例子中,代碼在循環內調用append并且這些調用涉及到一些其他的小知識,因此在這里起到的優化作用不大。希望這不會是一個痛點,但請務必進行基準測試,以確保自己代碼ok。

對于我們的例子,上述的做法帶來了(期望的)性能提升。事件代理對簡單的綁定是一種改進,可選的DocumentFragment也起到了助推作用。

var moduleD = function () { return {data: dataArray,init: function () { this.addTable(); this.addEvents();},addTable: function () { var td, tr; var frag = document.createDocumentFragment(); var frag2 = document.createDocumentFragment(); for (var i = 0; i < rows; i++) {tr = document.createElement('tr');for (var j = 0; j < this.data.length; j++) { td = document.createElement('td'); td.appendChild(document.createTextNode(this.data[j])); frag2.appendChild(td);}tr.appendChild(frag2);frag.appendChild(tr); } tbody.appendChild(frag);},addEvents: function () { $('table').on('click', 'td', function () {$(this).toggleClass('active'); });} };}();

接下來看看其他提升性能的方式。你也許曾經在哪讀到過使用原型模式比模塊模式更優,或聽說過使用JS模版框架性能更好。有時的確如此,不過使用它們其實是為了代碼更具可讀性。對了,還有預編譯!讓我們看看在實踐中表現的如何?

moduleG = function () {};moduleG.prototype.data = dataArray;moduleG.prototype.init = function () { this.addTable(); this.addEvents();};moduleG.prototype.addTable = function () { var template = _.template($('#template').text()); var html = template({'data' : this.data}); $tbody.append(html);};moduleG.prototype.addEvents = function () { $('table').on('click', 'td', function () { $(this).toggleClass('active'); });};var modG = new moduleG();

事實證明,在這種情況下的帶來的性能提升可以忽略不計。模板和原型的選擇并沒有真正提供更多的東西。也就是說,性能并不是開發者使用它們的原因,給代碼帶來的可讀性、繼承模型和可維護性才是真正的原因。

更復雜的問題包括高效地在canvas上繪制圖片和操作帶或不帶類型數組的像素數據。

在將一些方法用在你自己的應用之前,一定要多了解這些方案的基準測試。也許有人還記得JS模版的shoot-off和隨后的擴展版。你要搞清楚基準測試不是存在于你看不到的那些虛擬應用,而是應該在你的實際代碼中去測試帶來的優化。

  V8優化技巧

詳細介紹了每個V8引擎的優化點在本文討論范圍之外,當然這里也有許多值得一提的技巧。記住這些技巧你就能減少那些性能低下的代碼了。

特定模式可以使V8擺脫優化的困境,比如說try-catch。欲了解更多有關哪些函數能或不能進行優化,你可以在V8的腳本工具d8中使用–trace-opt file.js命令。如果你關心速度,盡量使你的函數職責單一,即確保變量(包括屬性,數組,函數參數)只使用相同隱藏類包含的對象。舉個例子,別這么干:

function add(x, y) { return x+y;}add(1, 2);add('a','b');add(my_custom_object, undefined);不要加載未初始化或已刪除的元素。如果這么做也不會出現什么錯誤,但是這樣會使速度變慢。不要使函數體過大,這樣會使得優化更加困難。

更多內容可以去看Daniel Clifford在Google I/O的分享 Breaking the JavaScript Speed Limit with V8。 Optimizing For V8 — A Series也非常值得一讀。

對象VS數組:我應該用哪個?

如果你想存儲一串數字,或者一些相同類型的對象,使用一個數組。如果你語義上需要的是一堆的對象的屬性(不同類型的),使用一個對象和屬性。這在內存方面非常高效,速度也相當快。整數索引的元素,無論存儲在一個數組或對象中,都要比遍歷對象的屬性快得多。對象的屬性比較復雜:它們可以被setter們創建,具有不同的枚舉性和可寫性。數組中則不具有如此的定制性,而只存在有和無這兩種狀態。在引擎層面,這允許更多存儲結構方面的優化。特別是當數組中存在數字時,例如當你需要容器時,不用定義具有x,y,z屬性的類,而只用數組就可以了。

JavaScript中對象和數組之間只有一個的主要區別,那就是數組神奇的length屬性。如果你自己來維護這個屬性,那么V8中對象和數組的速度是一樣快的。

使用對象時的技巧

使用一個構造函數來創建對象。這將確保它創建的所有對象具有相同的隱藏類,并有助于避免更改這些類。作為一個額外的好處,它也略快于Object.create()你的應用中,對于使用不同類型的對象和其復雜度(在合理的范圍內:長原型鏈往往是有害的,呈現只有一個極少數屬性的對象比大對象會快一點)是有沒限制的。對于“hot”對象,盡量保持短原型鏈,并且少屬性。

對象克隆

對于應用程序開發人員,對象克隆是一個常見的問題。雖然各種基準測試可以證明V8對這個問題處理得很好,但仍要小心。復制大的東西通常是較慢的——不要這么做。JS中的for..in循環尤其糟糕,因為它有著惡魔般的規范,并且無論是在哪個引擎中,都可能永遠不會比任何對象快。

當你一定要在關鍵性能代碼路徑上復制對象時,使用數組或一個自定義的“拷貝構造函數”功能明確地復制每個屬性。這可能是最快的方式:

function clone(original) { this.foo = original.foo; this.bar = original.bar;}var copy = new clone(original);

模塊模式中緩存函數

使用模塊模式時緩存函數,可能會導致性能方面的提升。參閱下面的例子,因為它總是創建成員函數的新副本,你看到的變化可能會比較慢。

另外請注意,使用這種方法明顯更優,不僅僅是依靠原型模式(經過jsPerf測試確認)。

編寫高性能JavaScript

使用模塊模式或原型模式時的性能提升

這是一個原型模式與模塊模式的性能對比測試:

// Prototypal pattern Klass1 = function () {} Klass1.prototype.foo = function () { log('foo'); } Klass1.prototype.bar = function () { log('bar'); } // Module pattern Klass2 = function () { var foo = function () { log('foo'); }, bar = function () { log('bar'); }; return { foo: foo, bar: bar } } // Module pattern with cached functions var FooFunction = function () { log('foo'); }; var BarFunction = function () { log('bar'); }; Klass3 = function () { return { foo: FooFunction, bar: BarFunction } } // Iteration tests // Prototypal var i = 1000, objs = []; while (i--) { var o = new Klass1() objs.push(new Klass1()); o.bar; o.foo; } // Module pattern var i = 1000, objs = []; while (i--) { var o = Klass2() objs.push(Klass2()); o.bar; o.foo; } // Module pattern with cached functions var i = 1000, objs = []; while (i--) { var o = Klass3() objs.push(Klass3()); o.bar; o.foo; }// See the test for full details

使用數組時的技巧

接下來說說數組相關的技巧。在一般情況下,不要刪除數組元素,這樣將使數組過渡到較慢的內部表示。當索引變得稀疏,V8將會使元素轉為更慢的字典模式。

數組字面量

數組字面量非常有用,它可以暗示VM數組的大小和類型。它通常用在體積不大的數組中。

// Here V8 can see that you want a 4-element array containing numbers:var a = [1, 2, 3, 4];// Don't do this:a = []; // Here V8 knows nothing about the arrayfor(var i = 1; i <= 4; i++) { a.push(i);}

存儲單一類型VS多類型

將混合類型(比如數字、字符串、undefined、true/false)的數據存在數組中絕不是一個好想法。例如var arr = [1, “1”, undefined, true, “true”]

類型推斷的性能測試

正如我們所看到的結果,整數的數組是最快的。

稀疏數組與滿數組

當你使用稀疏數組時,要注意訪問元素將遠遠慢于滿數組。因為V8不會分配一整塊空間給只用到部分空間的數組。取而代之的是,它被管理在字典中,既節約了空間,但花費訪問的時間。

稀疏數組與滿數組的測試

預分配空間VS動態分配

不要預分配大數組(如大于64K的元素),其最大的大小,而應該動態分配。在我們這篇文章的性能測試之前,請記住這只適用部分JavaScript引擎。

編寫高性能JavaScript

空字面量與預分配數組在不同的瀏覽器進行測試

Nitro (Safari)對預分配的數組更有利。而在其他引擎(V8,SpiderMonkey)中,預先分配并不是高效的。

預分配數組測試

// Empty arrayvar arr = [];for (var i = 0; i < 1000000; i++) { arr[i] = i;}// Pre-allocated arrayvar arr = new Array(1000000);for (var i = 0; i < 1000000; i++) { arr[i] = i;}

優化你的應用

在Web應用的世界中,速度就是一切。沒有用戶希望用一個要花幾秒鐘計算某列總數或花幾分鐘匯總信息的表格應用。這是為什么你要在代碼中壓榨每一點性能的重要原因。

編寫高性能JavaScript

  圖片來源: Per Olof Forsberg.

理解和提高應用程序的性能是非常有用的同時,它也是困難的。我們推薦以下的步驟來解決性能的痛點:

測量:在您的應用程序中找到慢的地方(約45%)理解:找出實際的問題是什么(約45%)修復它! (約10%)

下面推薦的一些工具和技術可以協助你。

基準化(BENCHMARKING)

有很多方式來運行JavaScript代碼片段的基準測試其性能——一般的假設是,基準簡單地比較兩個時間戳。這中模式被jsPerf團隊指出,并在SunSpider和Kraken的基準套件中使用:

var totalTime, start = new Date, iterations = 1000;while (iterations--) { // Code snippet goes here}// totalTime → the number of milliseconds taken// to execute the code snippet 1000 timestotalTime = new Date - start;

在這里,要測試的代碼被放置在一個循環中,并運行一個設定的次數(例如6次)。在此之后,開始日期減去結束日期,就得出在循環中執行操作所花費的時間。

然而,這種基準測試做的事情過于簡單了,特別是如果你想運行在多個瀏覽器和環境的基準。垃圾收集器本身對結果是有一定影響的。即使你使用window.performance這樣的解決方案,也必須考慮到這些缺陷。

不管你是否只運行基準部分的代碼,編寫一個測試套件或編碼基準庫,JavaScript基準其實比你想象的更多。如需更詳細的指南基準,我強烈建議你閱讀由Mathias Bynens和John-David Dalton提供的Javascript基準測試。

分析(PROFILING)

Chrome開發者工具為JavaScript分析有很好的支持。可以使用此功能檢測哪些函數占用了大部分時間,這樣你就可以去優化它們。這很重要,即使是代碼很小的改變會對整體表現產生重要的影響。

編寫高性能JavaScript

Chrome開發者工具的分析面板

分析過程開始獲取代碼性能基線,然后以時間線的形式體現。這將告訴我們代碼需要多長時間運行。“Profiles”選項卡給了我們一個更好的視角來了解應用程序中發生了什么。JavaScript CPU分析文件展示了多少CPU時間被用于我們的代碼,CSS選擇器分析文件展示了多少時間花費在處理選擇器上,堆快照顯示多少內存正被用于我們的對象。

利用這些工具,我們可以分離、調整和重新分析來衡量我們的功能或操作性能優化是否真的起到了效果。

編寫高性能JavaScript

“Profile”選項卡展示了代碼性能信息。

一個很好的分析介紹,閱讀Zack Grossbart的 JavaScript Profiling With The Chrome Developer Tools。

提示:在理想情況下,若想確保你的分析并未受到已安裝的應用程序或擴展的任何影響,可以使用--user-data-dir <empty_directory>標志來啟動Chrome。在大多數情況下,這種方法優化測試應該是足夠的,但也需要你更多的時間。這是V8標志能有所幫助的。

避免內存泄漏——3快照技術

在谷歌內部,Chrome開發者工具被Gmail等團隊大量使用,用來幫助發現和排除內存泄漏。

編寫高性能JavaScript

Chrome開發者工具中的內存統計

內存統計出我們團隊所關心的私有內存使用、JavaScript堆的大小、DOM節點數量、存儲清理、事件監聽計數器和垃圾收集器正要回收的東西。推薦閱讀Loreena Lee的“3快照”技術。該技術的要點是,在你的應用程序中記錄一些行為,強制垃圾回收,檢查DOM節點的數量有沒有恢復到預期的基線,然后分析三個堆的快照來確定是否有內存泄漏。

單頁面應用的內存管理

單頁面應用程序(例如AngularJS,Backbone,Ember)的內存管理是非常重要的,它們幾乎永遠不會刷新頁面。這意味著內存泄漏可能相當明顯。移動終端上的單頁面應用充滿了陷阱,因為設備的內存有限,并在長期運行Email客戶端或社交網絡等應用程序。能力愈大責任愈重。

有很多辦法解決這個問題。在Backbone中,確保使用dispose()來處理舊視圖和引用(目前在Backbone(Edge)中可用)。這個函數是最近加上的,移除添加到視圖“event”對象中的處理函數,以及通過傳給view的第三個參數(回調上下文)的model或collection的事件監聽器。dispose()也會被視圖的remove()調用,處理當元素被移除時的主要清理工作。Ember 等其他的庫當檢測到元素被移除時,會清理監聽器以避免內存泄漏。

Derick Bailey的一些明智的建議:

與其了解事件與引用是如何工作的,不如遵循的標準規則來管理JavaScript中的內存。如果你想加載數據到的一個存滿用戶對象的Backbone集合中,你要清空這個集合使它不再占用內存,那必須這個集合的所有引用以及集合內對象的引用。一旦清楚了所用的引用,資源就會被回收。這就是標準的JavaScript垃圾回收規則。

在文章中,Derick涵蓋了許多使用Backbone.js時的常見內存缺陷,以及如何解決這些問題。

Felix Geisendörfer的在Node中調試內存泄漏的教程也值得一讀,尤其是當它形成了更廣泛SPA堆棧的一部分。

減少回流(REFLOWS)

當瀏覽器重新渲染文檔中的元素時需要 重新計算它們的位置和幾何形狀,我們稱之為回流。回流會阻塞用戶在瀏覽器中的操作,因此理解提升回流時間是非常有幫助的。

編寫高性能JavaScript

回流時間圖表

你應該批量地觸發回流或重繪,但是要節制地使用這些方法。盡量不處理DOM也很重要。可以使用DocumentFragment,一個輕量級的文檔對象。你可以把它作為一種方法來提取文檔樹的一部分,或創建一個新的文檔“片段”。與其不斷地添加DOM節點,不如使用文檔片段后只執行一次DOM插入操作,以避免過多的回流。

例如,我們寫一個函數給一個元素添加20個div。如果只是簡單地每次append一個div到元素中,這會觸發20次回流。

function addDivs(element) { var div; for (var i = 0; i < 20; i ++) { div = document.createElement('div'); div.innerHTML = 'Heya!'; element.appendChild(div); }}

要解決這個問題,可以使用DocumentFragment來代替,我們可以每次添加一個新的div到里面。完成后將DocumentFragment添加到DOM中只會觸發一次回流。

function addDivs(element) { var div; // Creates a new empty DocumentFragment. var fragment = document.createDocumentFragment(); for (var i = 0; i < 20; i ++) { div = document.createElement('a'); div.innerHTML = 'Heya!'; fragment.appendChild(div); } element.appendChild(fragment);}

可以參閱 Make the Web Faster,JavaScript Memory Optimization 和 Finding Memory Leaks。

JS內存泄漏探測器

為了幫助發現JavaScript內存泄漏,谷歌的開發人員((Marja Hölttä和Jochen Eisinger)開發了一種工具,它與Chrome開發人員工具結合使用,檢索堆的快照并檢測出是什么對象導致了內存泄漏。

編寫高性能JavaScript

一個JavaScript內存泄漏檢測工具

有完整的文章介紹了如何使用這個工具,建議你自己到內存泄漏探測器項目頁面看看。

如果你想知道為什么這樣的工具還沒集成到我們的開發工具,其原因有二。它最初是在Closure庫中幫助我們捕捉一些特定的內存場景,它更適合作為一個外部工具。

V8優化調試和垃圾回收的標志位

Chrome支持直接通過傳遞一些標志給V8,以獲得更詳細的引擎優化輸出結果。例如,這樣可以追蹤V8的優化:

"/Applications/Google Chrome/Google Chrome" --js-flags="--trace-opt --trace-deopt"

Windows用戶可以這樣運行 chrome.exe –js-flags=”–trace-opt –trace-deopt”

在開發應用程序時,下面的V8標志都可以使用。

trace-opt —— 記錄優化函數的名稱,并顯示跳過的代碼,因為優化器不知道如何優化。trace-deopt —— 記錄運行時將要“去優化”的代碼。trace-gc —— 記錄每次的垃圾回收。

V8的處理腳本用*(星號)標識優化過的函數,用~(波浪號)表示未優化的函數。

如果你有興趣了解更多關于V8的標志和V8的內部是如何工作的,強烈建議 閱讀Vyacheslav Egorov的excellent post on V8 internals。

HIGH-RESOLUTION TIME 和 NAVIGATION TIMING API

高精度時間(HRT)是一個提供不受系統時間和用戶調整影響的亞毫秒級高精度時間接口,可以把它當做是比 new Date 和 Date.now()更精準的度量方法。這對我們編寫基準測試幫助很大。

編寫高性能JavaScript

高精度時間(HRT)提供了當前亞毫秒級的時間精度

目前HRT在Chrome(穩定版)中是以window.performance.webkitNow()方式使用,但在Chrome Canary中前綴被丟棄了,這使得它可以通過window.performance.now()方式調用。Paul Irish在HTML5Rocks上了關于HRT更多內容的文章。

現在我們知道當前的精準時間,那有可以準確測量頁面性能的API嗎?好吧,現在有個Navigation Timing API可以使用,這個API提供了一種簡單的方式,來獲取網頁在加載呈現給用戶時,精確和詳細的時間測量記錄。可以在console中使用window.performance.timing來獲取時間信息:

編寫高性能JavaScript

顯示在控制臺中的時間信息

我們可以從上面的數據獲取很多有用的信息,例如網絡延時為responseEnd – fetchStart,頁面加載時間為loadEventEnd – responseEnd,處理導航和頁面加載的時間為loadEventEnd – navigationStart。

正如你所看到的,perfomance.memory的屬性也能顯示JavaScript的內存數據使用情況,如總的堆大小。

更多Navigation Timing API的細節,閱讀 Sam Dutton的 Measuring Page Load Speed With Navigation Timing。

ABOUT:MEMORY 和 ABOUT:TRACING

Chrome中的about:tracing提供了瀏覽器的性能視圖,記錄了Chrome的所有線程、tab頁和進程。

編寫高性能JavaScript

About:Tracing提供了瀏覽器的性能視圖

這個工具的真正用處是允許你捕獲Chrome的運行數據,這樣你就可以適當地調整JavaScript執行,或優化資源加載。

Lilli Thompson有一篇寫給游戲開發者的使用about:tracing分析WebGL游戲的文章,同時也適合JavaScript的開發者。

在Chrome的導航欄里可以輸入about:memory,同樣十分實用,可以獲得每個tab頁的內存使用情況,對定位內存泄漏很有幫助。

總結

我們看到,JavaScript的世界中有很多隱藏的陷阱,且并沒有提升性能的銀彈。只有把一些優化方案綜合使用到(現實世界)測試環境,才能獲得最大的性能收益。即便如此,了解引擎是如何解釋和優化代碼,可以幫助你調整應用程序。

測量,理解,修復。不斷重復這個過程。

編寫高性能JavaScript

圖片來源: Sally Hunter

謹記關注優化,但為了便利可以舍棄一些很小的優化。例如,有些開發者選擇.forEach和Object.keys代替for和for..in循環,盡管這會更慢但使用更方便。要保證清醒的頭腦,知道什么優化是需要的,什么優化是不需要的。

同時注意,雖然JavaScript引擎越來越快,但下一個真正的瓶頸是DOM。回流和重繪的減少也是重要的,所以必要時再去動DOM。還有就是要關注網絡,HTTP請求是珍貴的,特別是移動終端上,因此要使用HTTP的緩存去減少資源的加載。

記住這幾點可以保證你獲取了本文的大部分信息,希望對你有所幫助!

英文鏈接:Writing Fast, Memory-Efficient JavaScript

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 欧美日本一区二区三区 | 久久精品99国产精品日本 | 欧美久久不卡 | 欧美综合久久 | 欧美一级片在线观看 | 一区二区日韩 | 亚洲午夜视频 | 日本福利视频网 | 日本久久网 | 国产一区二区欧美 | 国产91在线视频 | 亚洲黄色一级毛片 | 日日夜夜天天 | 久久久.com | 蜜臀网| 国产一区二区三区av在线 | 野狼在线社区2017入口 | 91高清在线观看 | 日韩日b视频| 色网在线观看 | 国产精品久久片 | 亚洲国产精品99久久久久久久久 | 91精品久久久久久久久 | 亚洲免费在线视频 | 每日更新av | 亚洲人久久| 国产黄色av| 国产第一区在线观看 | 精品国产乱码久久久久久久软件 | 久久久久久久国产精品 | 国产美女视频一区 | 日韩午夜电影在线观看 | 国产精品18久久久久久久久久久久 | 亚洲精品久久久久久下一站 | 韩国av片在线观看 | 99精品欧美一区二区三区 | 91免费看 | 欧美日韩精品久久久 | 精品成人| 99视频网 | 成人国产精品视频 | 亚洲www啪成人一区二区 | 国产一级黄色大片 | 欧美一区二区三区xxxx监狱 | 国产午夜精品一区二区三区 | 国产精品一区免费在线观看 | 欧美在线观看一区 | 亚洲一区二区在线免费观看 | 国产精品不卡视频 | 国产免费一区二区三区网站免费 | 在线观看视频一区二区三区 | 日韩国伦理久久一区 | 蜜桃视频一区二区 | 成人在线视频观看 | 成人欧美一区二区三区白人 | 国产精品久久久久久妇女6080 | 在线看国产| 欧美性hd | 日本a网| 日韩视频在线免费播放 | 欧美一区成人 | 国产精品久久久久影院色老大 | av中文字幕在线 | 狠狠干狠狠干 | 韩日精品 | 91男女视频 | 日韩激情二区 | 欧美日韩在线不卡 | 日韩综合视频在线观看 | 日韩成人在线视频 | 天堂资源最新在线 | 亚洲日韩aⅴ在线视频 | 中文字幕视频三区 | 91九色视频在线 | 日本精品一区二区三区在线观看视频 | 久久精品91| 亚洲国产成人在线视频 | 精品无人乱码区1区2区3区 | 韩日视频在线观看 | 国产精品99 | 色xx综合网 | 国产精品日本一区二区在线播放 | 欧美日韩中文在线观看 | 欧美日韩亚洲视频 | 成人国产一区 | 特级做a爰片毛片免费看108 | 日韩中文字幕无码一区二区三区 | 亚洲精品国产高清 | 国产激情91久久精品导航 | 曰韩在线 | 日韩一区二区三区在线播放 | 日本高清视频在线播放 | 2020亚洲视频 | 亚洲精久久| 久久久久无码国产精品一区 | 国产一区二区精品久久岳 | 亚洲一区二区三区视频 | 深夜成人小视频 | 日韩视频免费看 | 久在线视频播放免费视频 | 韩日一区 | 精品国产一区二区三区久久久蜜月 | 亚洲一区二区三区四区五区中文 | 日韩av网页 | 日韩欧美视频在线 | 亚洲一区久久 | 伊人网在线视频免费观看 | 一区二区三区精品视频免费看 | 91视频爱爱 | 亚洲一区二区三区日韩 | 亚洲一区二区三区免费在线观看 | 久久精品一区二区三区四区 | 国产亚洲www | 国产欧精精久久久久久久 | 国产一区亚洲二区三区 | 久久久久国产精品一区二区三区 | 精品成人av| 久久精av | 国产精品三级在线 | h视频免费在线 | 精品国产一区二区三区久久久蜜 | 亚洲精品国产电影 | 国产精品久久久一区二区三区 | 日韩3级 | 91在线高清观看 | 欧美日韩毛片 | 国产伦精品一区二区 | 国产精品视频久久 | 97国产精品 | 理伦影院 | 日韩爱爱免费视频 | h视频免费在线 | 69久久久| 亚洲第一黄色 | 日韩中文字幕免费在线 | 中文字幕日韩欧美一区二区三区 | 欧美另类综合 | 免费黄色片在线观看 | 99色综合| 欧美一级在线观看视频 | 玖玖精品在线 | 中文字幕视频在线 | 在线观看91| 9久久婷婷国产综合精品性色 | 波多野结衣三区 | a级在线| 欧美日韩在线综合 | 日本一区二区精品 | 国产精品久久久一区二区 | 亚洲综合无码一区二区 | 中国一级毛片免费 | 久久精品美女 | 黄色一级网站 | 欧美精品v国产精品v日韩精品 | 亚洲国产精品一区 | 亚洲成人精品视频 | 亚洲va中文字幕 | 91久久国产综合久久 | 亚洲精美视频 | 亚洲免费在线观看视频 | 91视频.www| 国产一区二区三区在线免费 | 高清久久 | 91在线精品一区二区 | 午夜午夜精品一区二区三区文 | 亚洲狠狠爱一区二区三区 | 久久久国产一区二区 | 国产视频一区二区 | 日韩一区二区三区在线观看 | 欧美视频网站 | 伊人久麻豆社区 | 日日日日干干干干 | 日本一本在线 | 亚洲av毛片一区二二区三三区 | 亚洲国产欧美在线 | 中文字幕第18页 | av资源中文在线天堂 | 日韩视频不卡 | 久久精品国产清自在天天线 | 中文字幕一区二区三区四区 | 天天色天天看 | 日韩一区二区三区在线观看 | 国产成人精品一区二区三区 | 嫩草私人影院 | 国产在线观看一区二区 | 国产成人精品久久二区二区 | 影音先锋中文字幕一区 | av一区二区三区四区 | 三级视频在线观看 | 亚洲精品一区二区三区在线看 | 亚洲精品在线播放 | 欧美日韩中文字幕 | 黑人一区| 看片地址 | 五月天在线婷婷 | 婷婷综合久久 | 午夜精品亚洲日日做天天做 | 欧美精品一区二区在线观看 | 九九亚洲 | 91免费版在线看 | 亚洲综合大片69999 | 黄色毛片在线播放 | 毛片网| 亚洲瑟瑟| 999视频在线免费观看 | 午夜av毛片 | 国产精品久久久久久久久免费丝袜 | 蜜桃精品久久久久久久免费影院 | 国产精品久久久久久久久久久久久 | 亚洲一区在线视频 | 欧美日韩大陆 | 青草青草久热精品视频在线观看 | 在线成人国产 | 亚洲国产欧美在线 | 亚洲欧美激情精品一区二区 | www.操操操| 久久精品国产视频 | 久久成人一区二区 | 亚洲成人av在线 | 91亚洲在线 | 久久久久成人精品 | 影视一区二区 | 91高清在线 | 亚洲一区二区三区久久久 | 日韩综合一区 | 国产精品久久久久国产精品 | 亚洲视频中文字幕 | 国产乱人伦av在线a jizz久久久 www.亚洲 | 日本狠狠色 | 国产在线精品一区二区三区 | 久久久一区二区 | 久久久久久国产精品mv | 国产精品视频一区二区免费不卡 | 亚洲一区二区高清视频 | 久久国产区 | 成人在线精品视频 | 国产xxx护士爽免费看 | 中文字幕国产视频 | 真实国产露脸乱 | 精品久久久久久久久久久久久久 | 国产视频导航 | 手机在线不卡av | 亚洲国产日韩欧美 | 国产在线精品一区二区三区 | 国产97色在线 | 亚洲 | 欧美一级免费看 | 日韩中文字幕在线 | 一区二区三区欧美在线 | 日韩精品一区二区三区 | 欧美日韩中文在线观看 | 国产色网站 | 国产精品一区二区三区在线播放 | 久草新免费| 久久成人国产精品 | 久久久久久成人 | 亚洲一区中文字幕永久在线 | 二区影院 | 欧美簧片在线 | 国产在线第一页 | 国产大片在线观看 | 国产成人精品一区二区三区在线 | 国产日韩一区二区三区 | 91视频观看 | 欧美成人精品一区二区三区 | 国内在线精品 | 午夜精品久久 | 亚洲精品久久久久久下一站 | 99精品视频网 | 伊人久久爱 | 免费午夜电影 | 美女黄网站视频免费 | 在线中文字幕视频 | 鲁一鲁影院 | 久久亚洲一区 | 国产精品一二 | 久久国产亚洲精品 | 九九热精 | 日韩欧美一区二区三区免费观看 | 亚洲一区二区福利 | 日本三级一区二区 | 国产精品欧美久久久久一区二区 | 蜜桃视频麻豆女神沈芯语免费观看 | 91传媒在线播放 | 在线观看国产视频 | 太子妃好紧皇上好爽h | 日韩啊啊啊 | 成人中文视频 | 精品一区二区三区免费 | 亚洲精品一二三四五区 | 亚洲三区在线观看 | 国产视频自拍一区 | av在线成人| 99热精品在线 | 日韩第一区 | 黑人巨大精品欧美一区免费视频 | 黄色一级免费电影 | 欧美精品一区二区三区四区在线 | 欧美日韩精品亚洲 | 精品久久久久一区二区国产 | 国产美女黄色片 | 国产不卡免费视频 | 玖玖在线免费视频 | 一区久久久 | 日韩视频一区二区 | 久久在线 | 天天看天天干 | 成人欧美一区二区三区在线观看 | 999在线观看精品免费不卡网站 | 亚洲精品一区二三区不卡 | 亚洲 欧美 日韩 在线 | 日本一区二区高清不卡 | 超碰免费在线观看 | 亚洲激情第一页 | 色婷婷综合久久久中文字幕 | 久久99精品久久久久久青青日本 | 久久久免费视频看看 | 91精品日韩| 国产aⅴ一区二区 | 天天操狠狠操 | 成人av网站在线观看 | www久久精品 | 色av综合| 欧美一区二区三区爽大粗免费 | 在线手机电影 | 伊人超碰 | av香港经典三级级 在线 | 黄网站色大毛片 | 免费观看成人性生生活片 | 毛片在线网站 | 精品国产一区二区三区久久影院 | 日韩a | 91亚洲国产成人久久精品网站 | 99久久久国产精品美女 | 久久久国产精品 | 欧美精品欧美极品欧美激情 | 天天干狠狠干 | av在线入口 | 国产精品激情在线观看 | 另类五月天 | 精品久久久久久国产 | 欧美精品黄 | 一区二区免费视频 | 国产一区二区av | 欧美激情精品久久久久 | 久久国产精品一区二区 | 精品国产一区二区三区在线观看 | 福利91 | 日本在线一区 | 精品欧美一区二区三区久久久小说 | 超级碰在线 | 羞羞羞网站 | 亚洲一区二区三区高清 | 国产99久久精品 | 97国产在线 | 亚洲欧美一区二区三区在线 | 9久久婷婷国产综合精品性色 | 一区二区三区视频播放 | 99国产精品99久久久久久 | 久色视频在线观看 | 国产精品毛片无码 | 中文字幕在线观看不卡视频 | 亚洲精品电影 | 欧美一级网站 | 狠狠干网站 | 国产精品三级久久久久久电影 | 9191视频| 北条麻妃99精品青青久久 | 亚洲一区二区三区在线 | 天天拍天天操 | 国产精品99久久免费观看 | 欧美一区二区三区免费观看视频 | 亚洲精品久久久久久一区二区 | 欧美一区二区三区精品 | 久久久久中文字幕 | av大片 | 一级欧美一级日韩 | 中文字幕视频 | 国产一级免费在线 | 成人片免费看 | 久热av在线| 91夜夜 | 中文字幕av在线 | 91视频免费观看 | 中文字幕一级毛片 | 日韩中文字幕视频 | 欧美精品一二三区 | 国产激情视频在线观看 | 在线欧美a | 日韩精品一区二区三区在线观看 | 亚洲国产情侣自拍 | 日本1区2区 | 国产精品久久久久久久久久10秀 | 欧美日韩视频一区二区 | 国产丝袜视频 | 97伦理电影网 | 成人国产精品一级毛片视频 | 成人国产一区 | 亚洲人成人一区二区在线观看 | 成年网站在线 | 另类a v| 欧产日产国产精品一二 | 日本黄色三级网站 | 亚洲国产99 | 国产精品久久久久一区二区三区 | 国产精品一区二区三区在线 | 久久午夜电影 | 黄色成人在线 | 91久色 | 国内精品视频一区国产 | 黄色大片视频 | 日本a在线| 在线激情网站 | 久草视频在线播放 | 亚洲成人在线视频网站 | 91精品久久久久久久久久入口 | 国产精彩视频 | 一区二区在线 | 久久精品久久久久电影 | 欧美三级视频在线播放 | 成人久久久精品国产乱码一区二区 | 99在线精品视频 | 国产精品日本一区二区不卡视频 | 亚洲 欧美 在线 一区 | 天天干天天插天天 | 欧美在线观看免费观看视频 | 日韩在线观看毛片 | 亚洲一区二区视频 | 国产午夜精品一区二区三区 | 在线观看中文字幕 | 色天天综合久久久久综合片 | 国产乱码一区二区三区在线观看 | 久久久精品网站 | 亚洲一区二区三区免费在线观看 | 日本三级欧美三级 | 91精品国产一区二区 | 亚洲欧美一区二区三区不卡 | 成人影视网址 | 久久精品亚洲精品国产欧美 | 欧州一区二区三区 | 日韩成人在线一区 | a级在线观看免费 | 狠狠入ady亚洲精品经典电影 | 精品久久久久久久久久久久久久久久久久久 | 99热精品久久 | 久久精品国产91精品亚洲高清 | 国产精品视频一二三区 | 色综合久久久 | 久久99久久久久 | 欧美一区久久 | 成人激情视频免费观看 | 成人片免费看 | 国产黄色在线免费看 | 国产精品久久久久久久久久久久冷 | 成人性大片免费观看网站 | 精品中文字幕一区 | 综合天天 | www亚洲成人 | 夫妻午夜影院 | 99精品欧美一区二区三区 | 蜜桃视频网站在线观看 | 香蕉久久久 | 欧美全黄 | 亚洲精品乱码久久久久久金桔影视 | 欧美一级精品片在线看 | 97成人在线 | 午夜视频在线观看网站 | 最近的中文字幕在线看视频 | 午夜寂寞少妇aaa片毛片 | 99精品国产一区二区三区 | 国产一区免费视频 | 国产99久久久精品视频 | 免费a视频| 男女视频免费 | 久久草草影视免费网 | 国产中文一区 | 国产高清在线视频 | 久久久一二三 | av一级毛片| 可以免费观看的av | 久久99国产精品 | av先锋资源 | 亚洲成人一区二区三区 | 国产午夜视频 | 日韩精品www | 激情毛片| 成年人在线观看视频 | 亚洲免费人成在线视频观看 | 久久精品网 | 99亚洲精品 | 欧美一级艳片视频免费观看 | 龙珠z国语291集普通话 | 狠狠爱天天操 | 亚洲精品视频一区 | 第一色站 | 成人在线免费电影 | 亚洲福利二区 | 羞羞在线观看视频免费观看hd | 成人 在线 | 成人国产精品视频 | av男人的天堂在线 | 国产大片黄色 | 福利三区| 日韩久久网站 | 欧美三级网| 成人亚洲 | 另类中文字幕 | 欧美激情视频一区二区三区在线播放 | 精品中文字幕一区二区 | 免费的黄色网 | 久草福利资源 | 国产精品网站在线 | 亚洲毛片在线观看 | 亚洲午夜精品片久久www慈禧 | 黄色国产一级片 | 国产视频一区二区 | 超碰天天 | 久久精品这里热有精品 | 中文字幕免费看 | 五月激情综合网 | 日韩性精品 | 国产精品成人3p一区二区三区 | 亚洲一区不卡 | 午夜欧美精品久久久久 | 精品成人免费一区二区在线播放 | 欧美日韩国产在线播放 | 久久久久久久国产 | 香蕉综合久久 | 久久精品二区 | 北条麻妃一区二区免费播放 | 91亚洲国产成人久久精品网站 | 亚洲色图一区二区三区 | 亚洲精品一区二区三区樱花 | 午夜在线观看视频网站 | 国产精品视频一区二区三区四 | 国产欧美在线播放 | a一级黄| 日日骚av| 精品中文字幕在线观看 | 欧美区国产 | 在线中文字幕av | 国产精品a久久 | 日韩精品在线一区 | 欧美成人精品一区二区男人看 | 色视频在线播放 | 91视频免费看 | www.avtt天堂网 | 亚洲精品久久久久久动漫 | 天天操天天色天天 | 亚洲永久免费 | 精品欧美激情在线观看 | 国产精品久久婷婷六月丁香 | 爱干视频| 久久婷婷色 | 互换娇妻呻吟hd中文字幕 | jlzzjlzz亚洲日本少妇 | 免费国产一区二区 | 黄网站免费在线 | 91色在线| 久久久国产一区二区三区 | 嫩草懂你 | 国产视频中文字幕 | 国产精品永久免费 | 国产免费一区二区三区最新不卡 | 日韩精品一区二区三区四区 | 国产大片在线观看 | 性xxxxxxxxx18欧美| 激情欧美一区二区三区中文字幕 | 国产电影一区二区三区图片 | 国产亚洲视频在线 | 欧美黄色一区 | 日韩亚洲在线 | 中文字幕精品一区久久久久 | 国产乱码精品1区2区3区 | 免费福利视频一区二区三区 | 精品亚洲视频在线 | 欧美一区 | 精品国产乱码久久久久久蜜臀 | 日韩精品免费观看 | 91视频www| 一区二区不卡 | 男女啪啪高清无遮挡 | 日韩一区精品视频 | 国产一区二区三区在线免费观看 | 久久国产一区二区三区 | 爱色区综合网 | 亚洲精品乱码久久久久久国产主播 | 久久久999精品视频 五月天婷婷在线视频 | 国产成人精品久久二区二区91 | 在线色站 | 久一区二区三区 | 成人免费小视频 | 欧美日韩电影一区 | 午夜免费在线 | 91精品久久久久久久久 | a级毛片免费高清视频 | 黄色大片免费网站 | 亚洲精品成人av | 91夜夜夜 | 99精品电影| 国产精品久久久久久久久久新婚 | 中文在线视频 | 97国产精品| 亚洲精品字幕 | 欧美在线高清 | 日韩精品一区二区三区在线观看 | 亚洲午夜精品视频 | 久久久一区二区 | 伊人在线 | 日日干,天天干 | 亚洲综合影院 | 久久久国色| 日本黄色一级电影 | 91社区在线播放 | 中文字幕在线视频精品 | 国产成人精品高清久久 |