前端技術-調試工具(下)

五.Profiles

這個主要是作性能優化的,包括查看CPU執行時間與內存佔用等。javascript

例述以下:原文地址:http://www.smashingmagazine.com/2012/06/12/javascript-profiling-chrome-developer-tools/css

你的網站正常運轉。如今咱們來讓它運轉的更快。網站的性能由頁面載入速度和代碼執行效率決定。一些服務可讓你的網站載入更快,好比壓縮JS和CDN,可是讓代碼執行的更快你要作的事情。
代碼中很小的改動均可能對性能形成巨大的影響。快速靈活的網站和可怕的「無響應腳本」對話框可能只有幾行代碼的差異。這篇文章告訴你如何經過用Chrome開發者工具(Chrome Developer Tools)找到這幾行關鍵的代碼。html

咱們來看一個簡單的「顏色排序器」應用,這個應用展現了一個由各類顏色構成的網格,你能夠拖拽這些顏色進行混合。每個點都是一個div標籤加上一些讓它看起來是圓的的CSS。前端

頁面載入的很快,但仍是花費了一些時間,在渲染以前還閃了一下。是時候對這個頁面進行性能分析讓它更快了。java

+設置一個基線

在開始作性能優化的時候要設置一個基線,來明確這個頁面的速度到底怎樣。這個基線可讓你知道本身是否作了優化並幫助你權衡利弊。
性能分析器(profiler)是chrome開發者工具的一部分,點擊小扳手下面的工具菜單就能夠打開它。Firebug也有一些性能評測工具,可是webkit內核的瀏覽器(chrome和safari)在對代碼進行性能分析和展現時間線方面是最棒的。Chrome還提供一種很棒的事件跟蹤工具,叫作 speed tracer。
在時間線(timeline)標籤下開始記錄,載入頁面而後中止記錄,這樣就設置了一個基線。(打開chrome開發者工具,點擊「時間線」標籤,而後點擊窗口底部圓形的黑色「記錄」圖標開始記錄)。我記錄了三次而後取了平均值,以防個人電腦在第一次測試的時候運行的很慢。程序員

用chrome開發者工具進行JS性能分析

個人平均基線,也就是從第一個請求到頁面所有渲染結束所花費的時間是1.25秒。這個時間不是太長,可是對於這樣一個小的頁面來講也不算好。我想讓代碼執行的更快,可是我並不知道是什麼讓它慢下來的。性能分析器(profiler)幫助我找到緣由。web

+建立一個Profile

時間線(timeline)告訴咱們代碼運行花費的時間,可是並無幫助咱們知道代碼運行的時候發生了什麼。profiler告訴咱們哪些函數的執行佔用了大部分時間。讓咱們切換到chrome開發者工具的「Profiles」標籤頁開始性能測試,這裏一共提供了三種類型的性能測試。chrome


一、javascript cpu 性能測試
顯示javascript佔用了多少CPU數據庫

二、css選擇器性能測試
顯示處理CSS選擇器佔用的CPU編程

三、堆棧快照
顯示javascript對象的內存佔用狀況

咱們想要javascript代碼執行的更快,因此咱們進行CPU性能測試。咱們開始性能測試,刷新頁面而後中止。

用chrome開發者工具進行JS性能分析

經過性能分析首先知道不少函數在執行。我發現列表最頂端的是decimalToHex和makeColorSorter兩個函數。這兩個函數佔用了CPU13.2%的時間,這是作優化的好地方。

咱們能夠點擊函數調用旁邊的「下一個」箭頭來查看完整的函數調用堆棧。展開後,能夠看到decimalToHex是被makeColorSorter調用的,makeColorSorter是經過$(document).ready調用的。

$(document).ready(function() {
    makeColorSorter(.05, .05, .05, 0, 2, 4, 128, 127, 121);
    makeSortable();
});

弄清楚這兩個函數是哪裏調用的,也就弄清楚了讓顏色能夠排序並非最大的性能問題。一般狀況下性能問題都是由多餘的排序操做形成的,可是在個人代碼中相比與排序增長DOM元素花費了更多時間。

我想要讓這些函數執行的更快,可是首先我想要將個人改動區隔開。在頁面載入過程當中會發生不少事情,我不想要這些影響到個人性能分析。

+區隔問題

我作了第二個版本,這個版本中「顏色排序器」在我點擊按鈕以後才載入,而不是在document ready的時候載入。這就把文檔載入的過程分離出去,讓我能夠只對顏色分類進行性能測試。調完性能以後我能夠馬上改回去。讓咱們調用新的函數testColorSorter並把它綁定到一個可點擊的按鈕上。

複製代碼
function testColorSorter() {
    makeColorSorter(.05, .05, .05, 0, 2, 4, 128, 127, 121);
    makeSortable();
}
1
<button id="clickMe" onclick="testColorSorter();">Click me</button>
複製代碼

在咱們進行性能分析以前改變應用可能致使意外的結果。這個改動看起來很安全,可是我仍是要從新運行性能檢測器來看看我是否是無心中改變了什麼。我會開始一次新的性能分析,點擊應用中的按鈕而後中止。

用chrome開發者工具進行JS性能分析

我首先注意到decimalToHex函數的載入只佔用了4.23%的時間。這是代碼執行花費時間最多的地方。咱們建立一個新的基線來看看這個方案對代碼有多大的優化。

用chrome開發者工具進行JS性能分析

有些事件在我點擊按鈕以前有觸發了,可是我只關注從我點擊鼠標到瀏覽器渲染「顏色排序器」花費的時間。鼠標在390毫秒時點擊,渲染事件在726毫秒處被觸發。726減去390獲得個人基線336毫秒。和第一個基線同樣我重複了3次來取平均值。

這時,我知道如何得到而且獲得了代碼確切的運行時間,咱們已經準備好開始解決問題了。

+讓代碼更高效

性能分析器只告訴咱們哪一個函數形成的問題,因此咱們要查看下函數的源碼來了解函數作了些什麼。

複製代碼
function decimalToHex(d) {
    var hex = Number(d).toString(16);
    hex = "00".substr(0, 2 - hex.length) + hex; 
 
    console.log('converting ' + d + ' to ' + hex);
    return hex;
}
複製代碼

「顏色排序器」中的每個顏色點都有一個16進制的色彩值,例如#86F01B和#2345FE.這些值表示一種顏色中紅,綠,藍三原色各自的數值。例如的背景色是#2456FE,表明紅色的值是36,綠色的值是86,藍色的是254,每個數值必須是0到255之間的。

decimalToHex函數把這用RGB值表示的顏色轉化爲頁面中咱們使用的16進制顏色。這個函數十分的簡單,可是我仍是留下了一個能夠去掉的調試代碼console.log在那裏。

decimalToHex 函數還在數字以前加上了補位。這是很重要的一點,由於有些10進制數字對應的是1個16進制數字。好比十進制中的10對應着16進制中的C,可是在CSS中須要一個兩位數。爲了讓這個進制換算更快速,咱們讓這段代碼不是那麼泛化。我知道每一個須要補位的數字長度都爲1,因此咱們能夠這樣重寫這個函數。

function decimalToHex(d) {
    var hex = Number(d).toString(16);
    return hex.length === 1 ? '0' + hex : hex; }

第三個版本的「顏色排序器」只有在須要補位的時候才改變字符串,而且不用調用substr函數。有了這個新函數,運行時間是137毫秒。再次對代碼進行性能測試,能夠發現decimalToHex函數只佔用了總時間的%0.04,到了列表的下部。用chrome開發者工具進行JS性能分析

咱們還能夠發現佔用CPU最多的函數是 jQuery的e.extend.merge。我不知道這個函數的做用,由於代碼是壓縮過的。我可使用開發版本的jQuery,可是我發現這個函數是被makeColorSorter調用的。因此下一步咱們先讓這個函數執行的更快。

+減少改動

「顏色排序器」中的多彩顏色是用過正弦曲線生成的。在光譜中設置一箇中心點,而後以必定的偏移來建立這個曲線。這就把顏色變成了一個「彩虹模型」。咱們還能夠經過改變紅綠藍三原色的使用頻率來改變顏色。

複製代碼
function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {
 
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);
 
       console.log('red: ' + decimalToHex(red));
       console.log('green: ' + decimalToHex(green));
       console.log('blue: ' + decimalToHex(blue));
 
       var div = $('<div class="colorBlock"></div>');
       div.css('background-color', '#' + decimalToHex(red) + decimalToHex(green) + decimalToHex(blue));
       $('#colors').append(div);
 
    }
}
複製代碼

咱們要去掉console.log函數。這些調用很是的糟糕,由於每次執行都會調用decimalToHex函數,這意味着decimalToHex函數會被多調用2倍的次數。這個函數大幅度的改變了DOM結構。每次循環,都向id爲colors的div中添加一個新的div。這就讓我懷疑這就是e.extend.mergefunction作的事情。用性能分析器作一個小實驗就能夠搞清楚。

我想要一次把全部的div添加進去,而不是在每一個循環中添加一個新的div。建立一個變量來存儲數據,而後在最後一次性添加進去。

複製代碼
function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {
 
    var colors = "";
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);
 
       colors += '<div class="colorBlock" style=" padding: 0px; line-height: 1.5 !important;"> 
           decimalToHex(red) + decimalToHex(green) + decimalToHex(blue) + '"></div>';
    }
 
    $('#colors').append(colors);
}
複製代碼

這個小改動意味着DOM只在添加全部div的時候作一次改變。用時間線進行測試,咱們發現從點擊到渲染花費了31毫秒。這個dom變更,使得第四個版本的運行時間下降了86%。我能夠再次打開性能分析器(profiler),發現e.extend.merge函數佔用了不多的時間,在列表中已經看不到它了。

咱們還能夠徹底移除decimalToHex函數讓代碼更快一點。由於CSS支持RGB顏色,因此咱們不須要把他們轉換到16進制。如今咱們能夠這樣寫makeColorSorter函數。

複製代碼
function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {
 
    var colors = "";
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);
 
       colors += '<div class="colorBlock" style=" padding: 0px; line-height: 1.5 !important;"> 
           red + ',' + green + ',' + blue + ')"></div>';
    }
 
    $('#colors').append(colors);
}
複製代碼

第五個版本的執行只用了26毫秒並且代碼行數從28行減小到18行。

在你的應用中進行Javascript性能分析

實際工做中的應用要比「顏色排序器」複雜的多,可是作性能分析要遵循一樣的基本原則

一、設置一個基線,這樣你就知道你是從何處開始的。

二、把問題從應用的其餘代碼隔離出來。

三、在一個可控的環境下進行優化,頻繁的使用時間線(timelines)和性能分析器(profiles)

還有一些性能優化的準則

一、從最慢的部分開始,這樣在時間優化上能夠獲得最大的提高。

二、控制環境。若是你換了電腦或者作了任何大的改動,都要設置新的基線。

三、屢次分析以防你電腦的異常致使獲得不正確的結果。

每一個人都想要他的網站更快,你必須開發新的功能,可是新的功能一般會讓網站更慢。因此花費時間來作性能優化是有價值的。

六.Resource

資源面板展現了頁面中的全部資源。

image_thumb10_thumb

一、資源面板tab;
二、左側欄分類列出頁面資源。如「框架」、「session存儲」,若是前面有箭頭點擊展開還能夠看到更多信息。注意左側欄的大小是能夠調整的;
三、頁面資源包括字體、圖片、js、css和頁面自己。若是頁面中有frame或iframe,展開Frames會看到其對應的frame和iframe。頁面層次結構更清晰
四、數據庫顯示頁面相關的SQL數據庫數據信息;
五、相應IndexedDB 也展現頁面的IndexedDB 信息;
六、以鍵/值 形式列表展現本地存儲的數據;
七、以鍵/值列表顯示session存儲數據;
八、根據域名列舉cookie;
九、顯示經過manifest緩存的資源。包括不少信息,如js庫文件會顯示文件地址、大小和類型;
十、右側用來顯示每一個資源對應的詳細信息。

雖然如今由frame組成的頁面愈來愈少見了,但查看框架內容的方法仍是有必要了解的。下面截圖,是一個由frame組成的頁面。

image_thumb12_thumb

+每一個frame都相關的資源都在一個文件夾下,一樣點擊展開能夠了解頁面的資源、js、css、圖片文件和字體狀況。點擊選中一個框架,頁面中其對應的區域會高亮顯示。
注:不會列出系統已有的,如「arial」「Helvetica」等,只會列出瀏覽器須要下載安裝的

+保存和查看資源

image_thumb131_thumb

+cookies

查看某個網站的cookie信息。如http://study.163.com/.

image_thumb17_thumb

[name]-字段名。如字段名爲「remember_checked」,其值爲1,這可能說明用戶在登錄的時候選擇了記住我;
[value]-字段所對應的值。如「_twitter_sess」所對應的值爲一串加密了的session ID;
[domain]-cookie所在的域。上圖的「.twitter.com」代表其子域也是能夠訪問該cookie的;
[path]-跟域相同,設置有效的路徑。設置爲「/」代表容許所在路徑下均可以訪問cookie;
[expires]-瀏覽器能夠刪除該cookie的日期;
[size]-cookie的大小,單位bytes;
[HTTP]-cookie的訪問容許HTTP協議。這能夠防止跨站js獲取cookie攻擊;
[secure]]-只容許加密鏈接訪問cookie,如HTTPS;

+緩存應用

[resource]-資源的完整路徑。典型的資源包括靜態資源和html文件,manifest文件也屬於其中;
[type]-能夠改變。Manifest文件的文件類型是Manifest,其餘的manifest文件中定義的文件類型爲explicit。Fallback類型的文件是那些須要回調資源文件的回調文件;
[size]-資源文件的大小,單位bytes;

七.Audits

用於優化前端頁面,加速網頁加載速度等。

使用Chrome瀏覽器對頁面性能進行檢測,根據測試的結果進行優化。固然這個結果只是參考,在實際的項目中確定有特殊狀況存在,並不能爲了知足某項測試結果而忽略特定狀況的存在。

一、Chrome檢測工具

點擊Audits而後出現了以下界面,選中重載頁面開始檢測按鈕,而後點擊Run按鈕,以後就是等待結果。

image_thumb22_thumb

二、檢測結果

這個檢測結果分爲2類,一個是網絡,一個是網頁性能;

檢測結果不只列出了問題,還定位問題在哪裏,能夠很快入手解決對應的問題。

1)合併JS文件:Combine external JavaScript(總共有29個能夠壓縮的JS文件)
2)There are multiple resources served from same domain. Consider combining them into as few files as possible.一個域名有多個文件,能夠考慮將他們壓縮爲儘量少的文件。

3)

4)啓用gzip壓縮:Enable gzip compression
5)Compressing the following resources with gzip could reduce their transfer size by about two thirds (~715 B).啓用gzip壓縮下降傳輸大小。

image_thumb26_thumb

6)

image_thumb29_thumb

7)瀏覽器緩存:Leverage browser caching 
8)The following resources are missing a cache expiration. Resources that do not specify an expiration may not be cached by browsers。資源沒有指定過時時間,瀏覽器可能不會緩存。

網頁性能部分
1)優化樣式和腳本的順序:Optimize the order of styles and scripts (4)

2)把CSS放到head中:Put CSS in the document head (3)
CSS in the document body adversely impacts rendering performance.

3)刪除沒用的CSS:Remove unused CSS rules (44)
44 rules (19%) of CSS not used by the current page.

4)Use normal CSS property names instead of vendor-prefixed ones (3)

應用:本身Css代碼的審覈;下載複製別人代碼,去除無用的Css樣式。可使用FireFox的Dust-Me selectors去除無用的Css樣式。

八.Console

1.console.log

你們都會用log,但鮮有人很好地利用console.error , console.warn 等將輸出到控制檯的信息進行分類整理。
他們功能區別不大,意義在於將輸出到控制檯的信息進行歸類,或者說讓它們更語義化。
各個所表明的語義以下:

console.log:普通訊息
console.info:提示類信息
console.error:錯誤信息
console.warn:警示信息

當合理使用上述log方法後,能夠很方便地在控制檯選擇查看特定類型的信息。

image_thumb33_thumb

若是再配合console.group 與console.groupEnd,能夠將這種分類管理的思想發揮到極致。這適合於在開發一個規模很大模塊不少很複雜的Web APP時,將各自的log信息分組到以各自命名空間爲名稱的組裏面。

image_thumb37_thumb

console.log第一個參數能夠包含一些格式化的指令好比%c,給hello word加了很炫的樣式(全是純CSS用來控制樣式的):

若是還不夠過癮,那我們來log一些圖片:

jdfw_thumb5_thumb1

除此,console.table 更是直接以表格的形式將數據輸出,不能贊得太多!

var data = [{'品名': 'X', '數量': 4}, {'品名': 'Y', '數量': 3}];
console.table(data);

image_thumb41_thumb

2.console.assert

當你想代碼知足某些條件時才輸出信息到控制檯,那麼你大可沒必要寫if或者三元表達式來達到目的,cosole.assert即是這樣場景下一種很好的工具,它會先對傳入的表達式進行斷言,只有表達式爲假時才輸出相應信息到控制檯。

image_thumb45_thumb

3.console.count

除了條件輸出的場景,還有常見的場景是計數。
當你想統計某段代碼執行了多少次時也大可沒必要本身去寫相關邏輯,內置的console.count能夠很地勝任這樣的任務。

image_thumb50_thumb

4.console.dir

將DOM結點以JavaScript對象的形式輸出到控制檯
而console.log是直接將該DOM結點以DOM樹的結構進行輸出,與在元素審查時看到的結構是一致的。不一樣的展示形式,一樣的優雅,各類體位任君選擇反正就是方便與體貼。

image_thumb63_thumb

5.console.time & console.timeEnd

輸出一些調試信息是控制檯最經常使用的功能,固然,它的功能遠不止於此。當作一些性能測試時,一樣能夠在這裏很方便地進行。
好比須要考量一段代碼執行的耗時狀況時,能夠用console.time與 console.timeEnd來作此事。

這裏借用官方文檔的例子:

image_thumb60_thumb

固然,咱們也能夠選擇本身寫代碼來計時:

image_thumb59_thumb

6.console.profile & console.timeLime

當想要查看CPU使用相關的信息時,可使用console.profile配合 console.profileEnd來完成這個需求。
這一功能能夠經過UI界面來完成,Chrome 開發者工具裏面有個tab即是Profile。

與此相似的功能還有console.timeLine配合 console.timeLineEnd,它的做用是開始記錄一段時間軸,一樣能夠經過Chrome開發者工具裏的Timeline 標籤來進行相應操做。

因此在我看來這兩個方法有點雞肋,由於均可以經過操做界面來完成。但至少他提供了一種命令行方式的交互,仍是多了種姿式供選擇吧。

7.console.trace

堆棧跟蹤相關的調試可使用console.trace。這個一樣能夠經過UI界面完成。當代碼被打斷點後,能夠在Call Stack面板中查看相關堆棧信息。

上面介紹的都是掛在window.console這個對象下面的方法,統稱爲Console API,接下來的這些方法確切地說應該叫命令,是Chrome內置提供,在控制檯中使用的,他們統稱爲Command Line API。

$

彷佛美刀老是被程序員及各類編程語言所青睞「你看看PHP代碼就知道PHPer有多愛錢了」,在Chrome的控制檯裏,便_命令返回最近一次表達式執行的結果,功能跟按向上的方向鍵再回車是同樣的,但它能夠作爲一個變量使用在你接下來的表達式中:

image_thumb66_thumb

上面的使0~45DOMDOM便0會返回最近一次點選的DOM結點,以此類推,$1返回的是上上次點選的DOM節點,最多保存了5個,若是不夠5個,則返回undefined。

另外值得一讚的是,Chrome 控制檯中原生支持類jQuery的選擇器,也就是說你能夠用$加上熟悉的css選擇器來選擇DOM節點

image_thumb69_thumb

(selector)滿DOM(selector)是原生JavaScript document.querySelector() 的封裝。
同時另外一個命令$$(selector)返回的是全部知足選擇條件的元素的一個集合,是對document.querySelectorAll() 的封裝。

copy

經過此命令能夠將在控制檯獲取到的內容複製到剪貼板。

copy(document.body);

keys & values

這是一對基友。前者返回傳入對象全部屬性名組成的數據,後者返回全部屬性值組成的數組。具體請看下面的例子:

image_thumb71_thumb

monitor & unmonitor

monitor(function),它接收一個函數名做爲參數,好比function a,每次a被執行了,都會在控制檯輸出一條信息,裏面包含了函數的名稱a及執行時所傳入的參數。

而unmonitor(function)即是用來中止這一監聽。

jdfw_thumb11_thumb1

debug & undebug

debug一樣也是接收一個函數名做爲參數。當該函數執行時自動斷下來以供調試,相似於在該函數的入口處打了個斷點,能夠經過debugger來作到,同時也能夠經過在Chrome開發者工具裏找到相應源碼而後手動打斷點。
而undebug 則是解除該斷點。

而其餘還有好些命令則讓人沒有說的慾望,由於好些均可以經過Chrome開發者工具的UI界面來操做而且比用在控制檯輸入要方便。

移動設備模式

如今不少的網頁都要適配移動端,Chrome的移動設備模式對開發者來講無疑是一個很大的驚喜。

點擊image_thumb_thumb,能夠模擬各類各樣的移動設備

image_thumb7_thumb

拖動模擬屏幕的標記的兩塊東西能任意調節設備屏幕大小

頂部橙色部分的選項,這個是選擇各類要模擬的設備

下面的是當前設備的顯示屏像素

image_thumb1
去掉前面的勾,或者點擊這個刪除的按鈕,網頁將會回到你如今的瀏覽器顯示大小

image_thumb2[1]
點這個還能快速切換橫屏豎屏

image_thumb3
這個是當前模擬的設備的像素比,例如:iPhone3GS是一、iphone4是二、iPhone6是3....

image_thumb4
若是你在操做的時候遇到這個警告,那麼你須要刷新下網頁才能看到實際的顯示效果

image_thumb6

這裏的這個Fit是若是你選擇的模擬設備像素的顯示範圍超過了你的瀏覽器框框,那麼就會根據你當前的顯示器高度和寬度自適應的縮放顯示比例。去掉勾選就是實際像素的顯示了。

image_thumb7[1]

而後咱們來看看右邊藍色的部分 第一個Network是用來模擬網絡環境的。你能夠模擬各類網絡環境以測試網頁的加載速度,甚至能夠模擬斷網的狀態...

image_thumb8_thumb

移動設備模式暫時就介紹到這裏。

---------------------------------------------------

就像開始說的,最主要的是本身多打開調試工具多點點,相信用多了就會熟悉。

轉載需註明轉載字樣,標註原做者和原博文地址。

前端技術-調試工具(上)

更多閱讀:

http://segmentfault.com/a/1190000000683599

http://www.ibm.com/developerworks/cn/web/1410_wangcy_chromejs/

相關文章
相關標籤/搜索