Your SlideShare is downloading. ×
0
Web Front-end performance Analyzerer                                梁剑钊                           2008 年 6 月
主题   为什么关注前端性能分析?   Yahoo 高性能网页最佳实践 (14+20)   前端性能分析工具    ◦   Fiddler    ◦   IBM Page Detailer    ◦   FireBug    ◦   Ya...
The sluggish Web 500 ms slower = 20% drop in traffic (Google) 100    ms slower = 1% drop in sales (Amazon)
Web User Perceive’s Response            time
A view of Webcommunications
The Life of Page 2.0                                   event handlers,   backend       fetching          components, user ...
The Importance of Front-End PerformanceBack-                                              Front-end=5%                    ...
What’s the Other 80%? Focus   on!  External                              RenderingComponents          +   Redirects   +   ...
The Performance GoldenRule80-90% of the end-user response time is spent on the front-end   Greater potential for improvem...
   为什么关注前端性能分析?   Yahoo 高性能网页最佳实践 (14+20)   前端性能分析工具    ◦   Fiddler    ◦   IBM Page Detailer    ◦   FireBug    ◦   Yaho...
The14 rules for high performance web sites   Make Fewer HTTP Requests                          content   Use a Content D...
High performance web pages 20 new best-practices 1.  Flush the buffer early                         server 2. Use GET for ...
   为什么关注前端性能分析?   Yahoo 高性能网页最佳实践 (14+20)   前端性能分析工具    ◦   Fiddler    ◦   IBM Page Detailer    ◦   FireBug    ◦   Yaho...
Web 前端工具   Firefox 阵营                       IE 堡垒    ◦   DOM Inspector                 ◦   IE Developer Toolbar    ◦   F...
IBM Page Detailer   Chart(IE7)
Maximizing Parallel Downloads                1.40                               average       36 x 36 px (0.9 Kb)   116 x ...
IBM Page Detailer details
FireBug Net Panel
YSlow 13 Rules for Fast WebPages_ 网页性能评分以及规则遵循             性
HTTP Analyzer3
AOL PageTest WaterFall        View
AOL PageTest OptimiztionCheckList
在线网页分析websiteoptimization
性能分析工具小结         FireBug Net PanelIBM Page Detailer                                              Methodology  Methodolog...
   为什么关注前端性能分析?   Yahoo 高性能网页最佳实践 (14+20)   前端性能分析工具    ◦   Fiddler    ◦   IBM Page Detailer    ◦   FireBug    ◦   Yaho...
DOM ReadyState   READYSTATE_UNINITIALIZED    ◦ Default initialization state.   READYSTATE_LOADING    ◦ Object is current...
PageTest 源码调试   Microsoft Visual Studio c++ 2008   Win32 Debug   IDE BHO 调试参数 : iexplore.exe
WSHook.cpp –winsock2 服务提供者wspStartup = new CAPIHook("msafd.dll", "WSPStartup", (PROC)::WSPStartup_Hook, TRUE);nspStartup =...
WinInet Hook ( 网络事件 )CWinInetHook::CWinInetHook(void):internetOpenA("wininet.dll", "InternetOpenA", (PROC)::InternetOpenA_...
IE BHO 技术
Win32 精确计时QueryPerformanceFrequency((LARGE_INTEGER *)&freq);msFreq = freq / (__int64)1000;…QueryPerformanceCounter((LARGE_...
render start time andDocument Complete time   the "render start time". This is the point at    which the browser first di...
CTestState::CheckRender 判断         render 起点 if( SUCCEEDED(tracker.browser-  >get_ReadyState(&rs)) && (rs ==  READYSTATE_...
CWatchDlg::DrawItemWaterfall      画出 render 比例图    const COLORREF colorRender = RGB( 40,188, 0);    hPenRender       = Cre...
PageTest 优化检查列表
优化定律   Don’t Optimize   Don’t Optimize anything you can’t measure   80/20 rule of Optimization    ◦ <20% retriving a ty...
   为什么关注前端性能分析?   Yahoo 高性能网页最佳实践 (14+20)   前端性能分析工具    ◦   Fiddler    ◦   IBM Page Detailer    ◦   FireBug    ◦   Yaho...
精减组件利器   Javascript 压缩工具    ◦ YUI Compressor    ◦ JSA: 国内开源    ◦ JSMin   图片优化工具    ◦ ImageMagick    ◦ Pngcrush : unix/wi...
   为什么关注前端性能分析?   Yahoo 高性能网页最佳实践 (14+20)   前端性能分析工具    ◦   Fiddler    ◦   IBM Page Detailer    ◦   FireBug    ◦   Yaho...
如何扩展前端分析工具   建立持续网页评估结果库及告警机制    ◦ 集成 YSlow 接口?    ◦ 扩充新 20 条?   建立持续网页速率监控池    ◦   扩展 PageTest    ◦   自主研发 BHO 工具    ◦ ...
Books
Links poolExceptional Performance: http:// performance.corp.yahoo.comYSlow?: http:// performance.corp.yahoo.com/docs/yslow...
Upcoming SlideShare
Loading in...5
×

Web前端性能分析工具导引

1,042

Published on

Published in: Technology, Design
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,042
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
27
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • http://www.cnblogs.com/guanhe/archive/2008/04/23/1167828.html “ 系统响应时间”指应用系统从请求发出开始到客户端接收到所有数据所消耗的时间。 这样,“系统响应时间”加上“呈现时间”,才是完整的用户感受到的响应时间。 用户点击“提交”按钮 - 》请求被发送到服务器 - 》服务器处理 - 》服务器返回页面 - 》浏览器接收服务器的返回并 render 页面 模糊之处在于最后一个环节:“ 浏览器接收服务器的返回并 render 页面 ”,如果我们坚定的认为“只有当页面完整的显示完成,才是响应时间的结束”,这不会是一个问题。但实际上,对大多数用户来说,看到页面上开始显示数据或是图片,用户就会认为“我已经得到了响应”,从这个角度来说,用户感受到的响应时间实际上是“ 从请求发出开始,到用户看到页面开始呈现出的内容结束 ”所需要的时间。 那为什么我们不采用“ 从请求发出开始,到用户看到页面开始呈现出的内容结束 ”这样一个定义方式呢?关键在于这里涉及到用户的认知行为,带有主观色彩,不完全是客观的标准,因此不适合作为一个需要被度量的性能指标。另一方面,不同的浏览器有不同的行为(例如 parse 的方式和 render 的方式),如果需要把这些浏览器本身的行为都考虑到性能测试中的话,我们很难为所有的系统建立统一的测试模型——实际上,现在的主流性能测试工具(例如 JMeter , LoadRunner , Webload 等) 都完全不考虑客户端的呈现过程。 http://www.javaworld.com/javaworld/jw-07-2005/jw-0711-jmeter.html?page=3 http://java.chinaitlab.com/tools/355421.html  在 web 应用的环境里,响应时间指的是从提交访问请求到等到 HTML 结果所耗费的时间。从技术的角度看,响应时间也应包括浏览器重绘 HTML 页面的时间,但是浏览器一般是一块接着一块地显示而不是直接显示完整的整个页面,让人感觉响应时间要少一些。 另外,典型的情况是,负载测试工具不会考虑浏览器的重绘时间。 因此, 在实际的性能测试中,我们将考虑以上描述的情形, 如果不能确信,可以在正常的响应时间上加一个固定值,如 0.5 秒。   以下是一套众所周知的确定相应时间的标准 :    · 用户将不会注意到少于 0.1 秒的延迟    · 少于 1 秒的延迟不会中断用户的正常思维, 但是一些延迟会被用户注意到    · 延迟时间少于 10 秒,用户会继续等待响应    · 延迟时间超过 10 秒后,用户将会放弃并开始其他操作   这些阀值很有名并且一般不会改变,因为是关乎人类的感知特性的。 所以要根据这些规则来设置响应时间需求, 也需要适当调整以适应实际应用。例如,亚马逊公司 (Amazon.com) 的主页也遵循了以上规则,但是由于更偏重于风格上的一致,所以在响应时间上有一点损失。
  • http://www.ibm.com/developerworks/websphere/library/techarticles/hipods/perform.html The communication progresses as follows: A client user enters a request (for example, a Web site name like www.ibm.com.). The browser application accepts the request, then typically uses the domain name service (DNS), a service of the User Datagram Protocol (UDP), to resolve fully qualified names (FQNs) such as www.ibm.com into Internet Protocol (IP) addresses such as 123.321.456.34. DNS builds a connection to the DNS server to obtain the IP address. When the browser receives the IP address, it initiates a Hypertext Transfer Protocol (HTTP) request. HTTP runs on the Transmission Control Protocol (TCP), which runs on IP, the network-layer protocol of the Internet. What happens next depends on whether communications are secured. If communications are not secured, the browser passes an HTTP request directly through TCP/IP, which creates a socket, a virtual mechanism to manage the addressing needed for sending the request and establishing the connection to the Web server. If communications are secured, the browser passes a secure HTTP (HTTPS) request to Socks, a security package that negotiates for transmission through the firewall. Such security negotiations occur both before sending the request and before receiving the response. The server also refers to the socket to accept the request and return the response through the firewall.
  • http://space.itpub.net/100788/viewspace-256935 http://www.codeproject.com/KB/aspnet/PageLifeCycle.aspx 呼应关系: READYSTATE_UNINITIALIZED Default initialization state. READYSTATE_LOADING Object is currently loading its properties. READYSTATE_LOADED Object has been initialized. – 获取完服务器原始数据,但不能直接在客户端使用 READYSTATE_INTERACTIVE Object is interactive, but not all of its data is available. ---- 正在解析数据 READYSTATE_COMPLETE Object has received all of its data.— 全部数据已解析完客户端可用的格式
  • An exceptional backend alone won’t get your far in terms of response time performance. Without cache, 5/95 split. With a primed cache, it still is 88% for FE.
  • Web Application Optimization is all about tuning your web application components to make your web application fast or appear fast.
  • 指导性能优化的方针
  • 1 reduce dns IE DnsCacheTimeout: 30 minutes KeepAliveTimeout: 1 minute ServerInfoTimeout: 2 minutes Firefox network.dnsCacheExpiration: 1 minute network.dnsCacheEntries: 20 network.http.keep-alive.timeout: 5 minutes Fasterfox: 1 hour, 512 entries, 30 seconds 最好网页能够 fewer hostnames – 2-4 , keep-alive
  • 1 让 HTML 缓冲内容提前推送到客户端。 Response.flush 与减少 http 请求是对立的 2 POST is a two-step process (send headers, send data) 而 get 请求仅仅使用一次请求, cookie 信息除外 3 The rest can wait (drag and drop, animations, hidden content, images below the fold) Onload 完成后执行 工具有 :YUI image loader,YUI Get utility 4 google Suggest, 智能提示 5 A complex page means more bytes to download It also means slower DOM access in JavaScript 不要滥用表格和 div 6 Maximize parallel downloads 组件从一台主机下载,响应时间受到并发线程数限制以及带宽限制。 但由于 DNS 开销损耗 But not more than 2-4 domains, because of the DNS lookup penalty Future: IE8 will allow 6 requests per domain 7 iframe: They have a cost even if blank They block page onload Non-semantic 8 When an external JavaScript is a 404, the browser will still try to parse it and find something usable in it The second component is a 404 JavaScript and it blocks the rest of the page 9 cookie 名字短小,设置域范围 10 创建子域存放静态的组件,减少 cookie 信息。 如 yahoo 的 yimg.com 11 采用缓存元素引用、避免直接操作 DOM 、避免用 JS 修改页面布局 12 Don&apos;t wait for onload , use DOMContentLoaded 采用事件委托机制。 YUI,JQuery,Prototype,Ext 13 import = 把 css 放在页面底部 14 IE proprietary AlphaImageLoader Fixes an IE6 problem with semi-transparent PNGs, IE7 is fine Blocks rendering, freezes the browser Increased memory consumption Per element, not per image! Best: Avoid completely, use gracefully degrading PNG8 Fallback: use underscore hack _filter not to penalize IE7+ users 16 多个小图片组合成一个大图片,然后用 CSS 技术对图片像素分割获取显示特定位置的图像。 17 如需要 100*100 的图片,就不要下载 500*500 的缩放图片 18 favicon.ico 根目录下的图片文件。 干扰正常的下载顺序。文件占总页面 PV 9% 。 19
  • 一 YSlow (http://developer.yahoo.com/yslow/) Fiddler (http://www.fiddlertool.com/fiddler/) IBM Page Detailer (http://www.alphaworks.ibm.com/tech/pagedetailer) HTTPWatch (http://www.httpwatch.com/) AOL Pagetest (http://pagetest.wiki.sourceforge.net/) Firebug Net Panel (http://www.getfirebug.com/) IE Leak Detector a.k.a Drip [ http://www.outofhanwell.com/ieleak/ ] Stopwatch profiling AjaxView [ http://research.microsoft.com/projects/ajaxview/ ] JsLex [ http://rockstarapps.com/pmwiki/pmwiki.php?n=JsLex.JsLex ] YUI profiler [ http://developer.yahoo.com/yui/profiler/ ] Venkman or Firebug Profiler [ http://www.getfirebug.com/ ] 二 Web Page Analyzer: 分析和测试网页速度。 Online Image Optimizer: 迅速简单的压缩您的图像。 Akamai Technologies: 提供大量的加速方案,特别是内容传输网络。 HTML-Optimizer: 清理 HTML 和脚本问题,例如不正确的标签、遗漏的属性和坏链接。 JSMin :承诺移除 JavaScript 文件的注解和不必要的白色地带,以便使网页加速。通常,这个工具可以使原文件大小减少一半。 PageTest: 测试您的网页的加载速度。 CSS Tweak: 优化样式表。 The JPEG Wizard Online Optimizer: 免费无损坏地压缩图像。 ShrinkSafe: 压缩文件大小,使代码更紧凑更少。 TRaceRT: 监控网页的速度、 DNS 和追踪轨迹。 mod_gzip: 在 Apache 网络服务器上压缩内容。 Clean CSS: 这个工具可以合并类似的选择,去除不必要的属性和白色地带。
  • 1 Browsers limits the number of connections to: four simultaneous connections (plus one queued connection) for a single HTTP 1.0 server, and two simultaneous connections to a single HTTP 1.1 server? Components are downloaded two or four at a time per hostname, depending on the HTTP server version. There are a couple exceptions to this rule that I just wanted to verbally mention: Firefox has default 8 connections Users can modify their configuration http://support.microsoft.com/?kbid=282402 http://kb.mozillazine.org/Network.http.max-connections http://kb.mozillazine.org/Network.http.max-connections-per-server http://kb.mozillazine.org/Network.http.max-persistent-connections-per-proxy http://kb.mozillazine.org/Network.http.max-persistent-connections-per-server 2 总耗时 3 IBM Page Detailer 支持 firefox 4 Nothing is rendered until all external CSS is downloaded 5 JS components block simultaneous downloads – all other download queues are not used. 6 首先,浏览器对于 script 的下载是避免并行进行的。 HTTP/1.1 协议中规定浏览器和同一 host 之间只建立最多两个连接,也就是说允许的最大并行度为 2 (当然,对 IE 和 Firefox 来说,你都可以通过修改浏览器的设置来扩大这个并行度)。但对于 Script 的下载来说,浏览器在开始下载 Script 之后,是不会并行的下载其他 element 的 7 http:// www.dbanotes.net/web/browser_connections_per_server.html 8 IBM Page Detailer 通过在客户端的 Windows 端口堆栈中插入探针( Probe )来获取相关信息 9 IBM Page Detailer 能够获取以下类型的数据: 总连接时间 端口连接时间和传输数据量 SSL 连接时间和传输数据量 Server 响应时间和传输数据量 内容传输时间和数据量 传输延迟时间 请求字节头 请求传输数据 反馈字节头 反馈数据内容 页面数总计,平均及最大、最小页面数
  • 并行下载线程数在 2 最合适。应该 &lt;4
  • Yahoo 推出的 Firebug 的性能分析插件 https://addons.mozilla.org/en-US/firefox/addon/5369
  • Group Level Timeline Chart The colored bars are used to express the relative timing of requests in the same group ( Webpage for IE Add-on, Process for Stand-alone) and the different phases of an HTTP request, e.g. blocked, connect, etc. The screen shot below shows a timeline from the google home page: Blocked The Blocked time includes any pre-processing time (such as cache lookup) and the time spent waiting for a network connection to become available. By default, IE allows only two outstanding connections per host name when talking to HTTP/1.1 servers or eight-ish outstanding connections total. Firefox has similar limits. Often the block time is the most significant factor in the time to download images embedded in the website. &amp;quot;Blocked&amp;quot; is available only in IE Add-on Edition DNS Lookup DNS Lookup represents the DNS Lookup time. It&apos;s the time that required to query a DNS name server to look up and find IP address information of computers in the internet. For example, resolve a host name (e.g. www.ieinspector.com) into a numeric IP address (e.g. 203.22.204.73). Connect Connect represents the TCP level connection time. It&apos;s the time that a new TCP level connection was established with web server(s) . If a secure HTTPS connection is being used this time includes the SSL handshake process. &amp;quot;Keep-alive&amp;quot; HTTP connections allow multiple requests to be send over the same TCP connection, and in some cases have been shown to result in an almost 50% speedup in latency times for HTML documents with lots of images. Send first to last Send represents the time required to send the HTTP request message to the server. This value will depend on the amount of data that is sent to the server. Wait Wait is the idle time taken to receive a response message from the server. This value includes network delay time and web server processing time. Receive first to last Receive is the time that receive the response message from the web server. This value will depend on the size of the return data, network bandwidth, as well as whether or not to use the HTTP compression method. Cache Read Cache Read is the time taken to read the content from the browser cache during (Cache) or 304 responses.
  • Each HTTP request is broken down into get IP, open socket, time to first byte, and content download all color coded on each waterfall chart
  • http://msdn.microsoft.com/en-us/library/ms534359(VS.85).aspx http://delphi.ktop.com.tw/board.php?cid=168&amp;fid=914&amp;tid=45908 http://msdn.microsoft.com/en-us/library/bb268229(VS.85).aspx http://msdn.microsoft.com/en-us/library/aa752084(VS.85).aspx http://www.cn-cuckoo.com/2007/07/16/the-details-for-five-states-of-readystate-9.html Applies To: document , FRAME , IFRAME , IMG , INPUT type=button , INPUT type=checkbox , INPUT type=file , INPUT type=hidden , INPUT type=image , INPUT type=password , INPUT type=radio , INPUT type=reset , INPUT type=submit , INPUT type=text , LINK , SCRIPT , TABLE , TBODY , TD , TFOOT , TH , THEAD , TR
  • Regsvr32 PageTest.dll 正式注册时才必须。
  • internetSetStatusCallback http://msdn.microsoft.com/en-us/library/aa383976(VS.85).aspx http://topic.csdn.net/t/20031211/11/2551790.html INTERNET_STATUS_CALLBACK CWinInetHook::InternetSetStatusCallbackN(HINTERNET hInternet, INTERNET_STATUS_CALLBACK lpfnInternetCallback) { INTERNET_STATUS_CALLBACK ret = NULL; // keep track of where the callbacks go for each hInternet EnterCriticalSection(&amp;cs); statusCallbacks.SetAt(hInternet, lpfnInternetCallback); LeaveCriticalSection(&amp;cs); // redirect the status callbacks to ourselves ret = ((LPINTERNETSETSTATUSCALLBACK)((PROC)internetSetStatusCallback))( hInternet, ::InternetStatusCallback ); return ret; } void CWinInetEvents::OnInternetStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) { if( active ) { EnterCriticalSection(&amp;cs); // locate the request CWinInetRequest * r = NULL; winInetRequests.Lookup(hInternet, r); LeaveCriticalSection(&amp;cs); if( r ) { __int64 beforeStart = r-&gt;start; switch(dwInternetStatus) { case INTERNET_STATUS_RESOLVING_NAME: { if( lpvStatusInformation ) r-&gt;hostName = (LPCSTR)lpvStatusInformation; if( !r-&gt;dnsStart ) QueryPerformanceCounter((LARGE_INTEGER*)&amp;(r-&gt;dnsStart)); if( !r-&gt;start ) r-&gt;start = r-&gt;dnsStart; ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_RESOLVING_NAME : %s\\n&amp;quot;), r-&gt;hRequest, (LPCTSTR)r-&gt;hostName); } break; case INTERNET_STATUS_NAME_RESOLVED: { ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_NAME_RESOLVED\\n&amp;quot;), r-&gt;hRequest); __int64 now; QueryPerformanceCounter((LARGE_INTEGER*)&amp;now); if( r-&gt;dnsStart ) { r-&gt;dnsEnd = now; r-&gt;tmDNS = now &lt;= r-&gt;dnsStart ? 0 : (DWORD)((now - r-&gt;dnsStart) / msFreq); } } break; case INTERNET_STATUS_CONNECTING_TO_SERVER: { if( !r-&gt;socketConnect ) QueryPerformanceCounter((LARGE_INTEGER*)&amp;(r-&gt;socketConnect)); if( !r-&gt;start ) r-&gt;start = r-&gt;socketConnect; // get the socket handle for the request if( !r-&gt;s ) { INTERNET_DIAGNOSTIC_SOCKET_INFO si; DWORD len = sizeof(si); if( InternetQueryOption( r-&gt;hRequest, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, &amp;si, &amp;len) ) { if( si.Flags &amp; IDSI_FLAG_SECURE ) r-&gt;secure = true; r-&gt;s = si.Socket; // lookup the socket ID EnterCriticalSection(&amp;cs); DWORD id = 0; socketID.Lookup(r-&gt;s, id); if( !id ) { id = nextSocketId; nextSocketId++; socketID.SetAt(r-&gt;s, id); } LeaveCriticalSection(&amp;cs); r-&gt;socketId = id; } } ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_CONNECTING_TO_SERVER\\n&amp;quot;), r-&gt;hRequest); } break; case INTERNET_STATUS_CONNECTED_TO_SERVER: { __int64 now; QueryPerformanceCounter((LARGE_INTEGER*)&amp;now); if( r-&gt;socketConnect ) { r-&gt;socketConnected = now; r-&gt;tmSocket = now &lt;= r-&gt;socketConnect ? 0 : (DWORD)((now - r-&gt;socketConnect) / msFreq); } // get the socket handle for the request if( !r-&gt;s ) { INTERNET_DIAGNOSTIC_SOCKET_INFO si; DWORD len = sizeof(si); if( InternetQueryOption( r-&gt;hRequest, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, &amp;si, &amp;len) ) { if( si.Flags &amp; IDSI_FLAG_SECURE ) r-&gt;secure = true; r-&gt;s = si.Socket; // lookup the socket ID EnterCriticalSection(&amp;cs); DWORD id = 0; socketID.Lookup(r-&gt;s, id); if( !id ) { id = nextSocketId; nextSocketId++; socketID.SetAt(r-&gt;s, id); } LeaveCriticalSection(&amp;cs); r-&gt;socketId = id; } EnterCriticalSection(&amp;cs); if( r-&gt;s &amp;&amp; !r-&gt;peer.sin_addr.S_un.S_addr ) { CSocketInfo * soc = NULL; openSockets.Lookup(r-&gt;s, soc); if( soc ) memcpy( &amp;r-&gt;peer, &amp;soc-&gt;address, sizeof(SOCKADDR_IN) ); } LeaveCriticalSection(&amp;cs); } ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_CONNECTED_TO_SERVER\\n&amp;quot;), r-&gt;hRequest); } break; case INTERNET_STATUS_SENDING_REQUEST: { // get the socket handle for the request if( !r-&gt;s ) { INTERNET_DIAGNOSTIC_SOCKET_INFO si; DWORD len = sizeof(si); if( InternetQueryOption( r-&gt;hRequest, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, &amp;si, &amp;len) ) { if( si.Flags &amp; IDSI_FLAG_SECURE ) r-&gt;secure = true; r-&gt;s = si.Socket; // lookup the socket ID EnterCriticalSection(&amp;cs); DWORD id = 0; socketID.Lookup(r-&gt;s, id); if( !id ) { id = nextSocketId; nextSocketId++; socketID.SetAt(r-&gt;s, id); } LeaveCriticalSection(&amp;cs); r-&gt;socketId = id; } EnterCriticalSection(&amp;cs); if( r-&gt;s &amp;&amp; !r-&gt;peer.sin_addr.S_un.S_addr ) { CSocketInfo * soc = NULL; openSockets.Lookup(r-&gt;s, soc); if( soc ) memcpy( &amp;r-&gt;peer, &amp;soc-&gt;address, sizeof(SOCKADDR_IN) ); } LeaveCriticalSection(&amp;cs); } if( !r-&gt;requestSent ) QueryPerformanceCounter((LARGE_INTEGER*)&amp;(r-&gt;requestSent)); if( !r-&gt;start ) r-&gt;start = r-&gt;requestSent; if( r-&gt;secure &amp;&amp; r-&gt;socketConnect &amp;&amp; r-&gt;tmSocket ) { r-&gt;tmSSL = r-&gt;requestSent &lt;= r-&gt;socketConnect ? 0 : (DWORD)((r-&gt;requestSent - r-&gt;socketConnect) / msFreq); if( r-&gt;tmSSL &gt; r-&gt;tmSocket ) r-&gt;tmSSL -= r-&gt;tmSocket; else r-&gt;tmSSL = 0; } // get the request headers TCHAR buff[10000]; DWORD len = sizeof(buff); DWORD index = 0; memset(buff, 0, len); if( HttpQueryInfo(r-&gt;hRequest, HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_RAW_HEADERS_CRLF , buff, &amp;len, &amp;index) ) r-&gt;outHeaders = buff; // get some specific headers we care about len = sizeof(buff); index = 0; memset(buff, 0, len); if( HttpQueryInfo(r-&gt;hRequest, HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_HOST , buff, &amp;len, &amp;index) ) r-&gt;host = buff; ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_SENDING_REQUEST, socket %d\\n&amp;quot;), r-&gt;hRequest, r-&gt;socketId); } break; case INTERNET_STATUS_REQUEST_SENT: { if( dwStatusInformationLength == sizeof(DWORD) &amp;&amp; lpvStatusInformation ) r-&gt;out += *((LPDWORD)lpvStatusInformation); ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_REQUEST_SENT : %d bytes\\n&amp;quot;), r-&gt;hRequest, r-&gt;out); } break; case INTERNET_STATUS_RECEIVING_RESPONSE: { ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_RECEIVING_RESPONSE\\n&amp;quot;), r-&gt;hRequest); } break; case INTERNET_STATUS_REDIRECT: { CString url = CA2T((LPCSTR)lpvStatusInformation); ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_REDIRECT : Redirecting to %s\\n&amp;quot;), r-&gt;hRequest, (LPCTSTR)url); // get the headers, close out the request and start a new one for the redirect r-&gt;Done(); // update the end time lastRequest = r-&gt;end; lastActivity = r-&gt;end; // update the in and out bytes from the raw socket if( r-&gt;linkedRequest ) { r-&gt;in = ((CSocketRequest *)r-&gt;linkedRequest)-&gt;in; r-&gt;out = ((CSocketRequest *)r-&gt;linkedRequest)-&gt;out; } // get the host IP address EnterCriticalSection(&amp;cs); if( r-&gt;s &amp;&amp; !r-&gt;peer.sin_addr.S_un.S_addr ) { CSocketInfo * soc = NULL; openSockets.Lookup(r-&gt;s, soc); if( soc ) memcpy( &amp;r-&gt;peer, &amp;soc-&gt;address, sizeof(SOCKADDR_IN) ); } LeaveCriticalSection(&amp;cs); // get the response code and headers TCHAR buff[10000]; DWORD len = sizeof(buff); DWORD index = 0; memset(buff, 0, len); if( HttpQueryInfo(r-&gt;hRequest, HTTP_QUERY_RAW_HEADERS_CRLF , buff, &amp;len, &amp;index) ) r-&gt;inHeaders = buff; // get the redirect code DWORD code; len = sizeof(code); index = 0; if( HttpQueryInfo(r-&gt;hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE , &amp;code, &amp;len, &amp;index) ) r-&gt;result = code; // remove it from the lookup OnInternetCloseHandle(r-&gt;hRequest); // create a new request CWinInetRequest * req = new CWinInetRequest(currentDoc); req-&gt;verb = r-&gt;verb; req-&gt;hRequest = r-&gt;hRequest; // split up the url URL_COMPONENTS parts; memset(&amp;parts, 0, sizeof(parts)); TCHAR host[10000]; TCHAR object[10000]; TCHAR extra[10000]; memset(host, 0, sizeof(host)); memset(object, 0, sizeof(object)); memset(extra, 0, sizeof(extra)); parts.lpszHostName = host; parts.dwHostNameLength = _countof(host); parts.lpszUrlPath = object; parts.dwUrlPathLength = _countof(object); parts.lpszExtraInfo = extra; parts.dwExtraInfoLength = _countof(extra); parts.dwStructSize = sizeof(parts); if( InternetCrackUrl((LPCTSTR)url, url.GetLength(), 0, &amp;parts) ) { req-&gt;host = host; req-&gt;object = CString(object) + extra; } EnterCriticalSection(&amp;cs); winInetRequests.SetAt(req-&gt;hRequest, req); LeaveCriticalSection(&amp;cs); AddEvent(req); } break; case INTERNET_STATUS_RESPONSE_RECEIVED: { if( dwStatusInformationLength == sizeof(DWORD) &amp;&amp; lpvStatusInformation ) r-&gt;in += *((LPDWORD)lpvStatusInformation); r-&gt;Done(true); // update the end time lastRequest = r-&gt;end; lastActivity = r-&gt;end; // update the in and out bytes from the raw socket if( r-&gt;linkedRequest ) { r-&gt;in = ((CSocketRequest *)r-&gt;linkedRequest)-&gt;in; r-&gt;out = ((CSocketRequest *)r-&gt;linkedRequest)-&gt;out; } ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_RESPONSE_RECEIVED : %d bytes\\n&amp;quot;), r-&gt;hRequest, r-&gt;in); } break; case INTERNET_STATUS_REQUEST_COMPLETE: { LPINTERNET_ASYNC_RESULT result = (LPINTERNET_ASYNC_RESULT)lpvStatusInformation; if( result ) r-&gt;result = result-&gt;dwError; // get the response code and headers TCHAR buff[10000]; DWORD len = sizeof(buff); DWORD index = 0; memset(buff, 0, len); if( HttpQueryInfo(r-&gt;hRequest, HTTP_QUERY_RAW_HEADERS_CRLF , buff, &amp;len, &amp;index) ) r-&gt;inHeaders = buff; if( !r-&gt;result || r-&gt;result == -1 ) { DWORD code; len = sizeof(code); index = 0; if( HttpQueryInfo(r-&gt;hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE , &amp;code, &amp;len, &amp;index) ) r-&gt;result = code; } len = sizeof(buff); if( InternetQueryOption(r-&gt;hRequest, INTERNET_OPTION_DATAFILE_NAME, buff, &amp;len) ) r-&gt;file = buff; // link this to the matching socket request EnterCriticalSection(&amp;cs); POSITION pos = requests.GetHeadPosition(); while( pos ) { CSocketRequest * req = requests.GetNext(pos); if( req &amp;&amp; req-&gt;s == r-&gt;s ) { req-&gt;linkedRequest = r; pos = 0; } } LeaveCriticalSection(&amp;cs); // update the &amp;quot;done&amp;quot; time r-&gt;Done(); // update the end time lastRequest = r-&gt;end; lastActivity = r-&gt;end; // update the in and out bytes from the raw socket if( r-&gt;linkedRequest ) { CSocketRequest * req = (CSocketRequest *)r-&gt;linkedRequest; r-&gt;in = req-&gt;in; r-&gt;out = req-&gt;out; if( req-&gt;response.code &amp;&amp; req-&gt;response.code != -1 ) r-&gt;result = req-&gt;response.code; } // make sure that we got an IP address for it EnterCriticalSection(&amp;cs); if( r-&gt;s &amp;&amp; !r-&gt;peer.sin_addr.S_un.S_addr ) { CSocketInfo * soc = NULL; openSockets.Lookup(r-&gt;s, soc); if( soc ) memcpy( &amp;r-&gt;peer, &amp;soc-&gt;address, sizeof(SOCKADDR_IN) ); } LeaveCriticalSection(&amp;cs); ATLTRACE(_T(&amp;quot;[Pagetest] - *** 0x%p - INTERNET_STATUS_REQUEST_COMPLETE\\n&amp;quot;), r-&gt;hRequest); } break; } // only add it to the list when it actually starts downloading if( !beforeStart &amp;&amp; r-&gt;start ) { __int64 realStart = r-&gt;start; AddEvent(r); r-&gt;start = realStart; } } // update the activity time QueryPerformanceCounter((LARGE_INTEGER *)&amp;lastActivity); CheckStuff(); } }
  • if( SUCCEEDED(tracker.browser-&gt;get_ReadyState(&amp;rs)) &amp;&amp; (rs == READYSTATE_INTERACTIVE || rs == READYSTATE_COMPLETE)) { CComQIPtr&lt;IHTMLDocument2&gt; doc = spDoc; CComQIPtr&lt;IHTMLDocument3&gt; doc3 = spDoc; CComPtr&lt;IHTMLElement&gt; body; if( doc &amp;&amp; SUCCEEDED(doc-&gt;get_body(&amp;body)) ) { CComQIPtr&lt;IHTMLElement2&gt; body2 = body; if( body2 ) { long width = 0; long height = 0; body2-&gt;get_scrollWidth(&amp;width); body2-&gt;get_scrollHeight(&amp;height); CComPtr&lt;IHTMLElement&gt; docElement; if( doc3 &amp;&amp; SUCCEEDED(doc3-&gt;get_documentElement(&amp;docElement)) ) { CComQIPtr&lt;IHTMLElement2&gt; docElement2 = docElement; if( docElement2 ) { long w2 = 0; long h2 = 0; docElement2-&gt;get_scrollWidth(&amp;w2); docElement2-&gt;get_scrollHeight(&amp;h2); width += w2; height += h2; } } if( width &amp;&amp; height ) QueryPerformanceCounter((LARGE_INTEGER *)&amp;startRender); } }
  • CTestState::DoStartup(CString&amp; szUrl) QueryPerformanceCounter((LARGE_INTEGER *)&amp;lastRequest); lastActivity = lastRequest; CBrowserEvents::BeforeNavigate QueryPerformanceCounter((LARGE_INTEGER *)&amp;lastRequest); lastActivity = lastRequest; void LineVert(HDC hDC, int x, int y0, int y1) { POINT line[2] = {{x,y0},{x,y1}}; Polyline(hDC, line, 2); }
  • /*----------------------------------------------------------------------------- See if the provided IP address belongs to a CDN -----------------------------------------------------------------------------*/ bool CPagetestReporting::IsCDN(CString host) { bool ret = false; if( !host.IsEmpty() ) { // make sure we haven&apos;t already identified it bool found = false; POSITION pos = cdnLookups.GetHeadPosition(); while( pos &amp;&amp; !found ) { CCDNEntry &amp;entry = cdnLookups.GetNext(pos); if( entry.name == host ) { found = true; ret = entry.isCDN; } } if( !found ) { // look it up and look at the cname entries for the host hostent * dnsinfo = gethostbyname(CT2A(host)); if( dnsinfo &amp;&amp; !WSAGetLastError() ) { // check the official name CStringA name = dnsinfo-&gt;h_name; name.MakeLower(); if( name.Find(&amp;quot;.akamai.net&amp;quot;) &gt; -1 || // Akamai name.Find(&amp;quot;.llnwd.net&amp;quot;) &gt; -1 || // Limelight name.Find(&amp;quot;edgecastcdn.net&amp;quot;) &gt; -1 || // Edgecast name.Find(&amp;quot;hwcdn.net&amp;quot;) &gt; -1 || // Highwinds name.Find(&amp;quot;.panthercdn.com&amp;quot;) &gt; -1 || // Panther name.Find(&amp;quot;.nyucd.net&amp;quot;) &gt; -1 // Coral Cache ) ret = true; } // add it to the list of resolved names CCDNEntry entry; entry.name = host; entry.isCDN = ret; cdnLookups.AddHead(entry); } } return ret; }
  • these factors and their related tradeoffs: Number, size, and complexity of items Number of connections Number of servers accessed Use of white space Load sequences Data security
  • Transcript of "Web前端性能分析工具导引"

    1. 1. Web Front-end performance Analyzerer 梁剑钊 2008 年 6 月
    2. 2. 主题 为什么关注前端性能分析? Yahoo 高性能网页最佳实践 (14+20) 前端性能分析工具 ◦ Fiddler ◦ IBM Page Detailer ◦ FireBug ◦ Yahoo YSlow ◦ HTTP Analyzer ◦ AOL PageTest PageTest 源码解读 优化定律 如何扩展前端工具
    3. 3. The sluggish Web 500 ms slower = 20% drop in traffic (Google) 100 ms slower = 1% drop in sales (Amazon)
    4. 4. Web User Perceive’s Response time
    5. 5. A view of Webcommunications
    6. 6. The Life of Page 2.0 event handlers, backend fetching components, user interaction, XHRs components XHRs requestrequest HTML page onload settles sent graduation marriage? R.I.P.conception birth fetus child User perceived “onload” teen happens somewhere here adult
    7. 7. The Importance of Front-End PerformanceBack- Front-end=5% end=95% Even Primed Cache, front-end= 88%
    8. 8. What’s the Other 80%? Focus on! External RenderingComponents + Redirects + (complicated by + DNS lookups(images, js, css) js and css) Requires extra HTTP requests! = 80% - 90%
    9. 9. The Performance GoldenRule80-90% of the end-user response time is spent on the front-end Greater potential for improvement 80-90% of the time Easier than the back-end目标 Faster loading times for pages Lesser amount of data to transfer Less load on the server
    10. 10.  为什么关注前端性能分析? Yahoo 高性能网页最佳实践 (14+20) 前端性能分析工具 ◦ Fiddler ◦ IBM Page Detailer ◦ FireBug ◦ Yahoo YSlow ◦ HTTP Analyzer ◦ AOL PageTest PageTest 源码解读 优化定律 如何扩展前端工具
    11. 11. The14 rules for high performance web sites Make Fewer HTTP Requests content Use a Content Delivery Network server Add Expires header (or Cache-control) server Gzip Components server Put CSS at the Top css Move Scripts to the Bottom (inline too) javascript Avoid CSS Expressions css Make JavaScript and CSS External css javascript Reduce DNS Lookups content Minify JavaScript and CSS (inline too) css javascript Avoid Redirects content Remove Duplicate Scripts javascript Configure ETags server Make AJAX Cacheable content
    12. 12. High performance web pages 20 new best-practices 1. Flush the buffer early server 2. Use GET for AJAX requests server 3. Post-load components content 4. Preload components content 5. Reduce the number of DOM elements content 6. Split components across domains content 7. Minimize the number of iframes content 8. No 404s content 9. Reduce cookie size cookie 10. Use cookie-free domains for components cookie 11. Minimize DOM access javascript 12. Develop smart event handlers javascript 13. Choose <link> over @import css 14. Avoid filters css images 15. Optimize images 16. Optimize CSS sprites images images 17. Dont scale images in HTML 18. Make favicon.ico small and cacheable images mobile 19. Keep components under 25K mobile 20. Pack components into a multipart document
    13. 13.  为什么关注前端性能分析? Yahoo 高性能网页最佳实践 (14+20) 前端性能分析工具 ◦ Fiddler ◦ IBM Page Detailer ◦ FireBug ◦ Yahoo YSlow ◦ HTTP Analyzer ◦ AOL PageTest PageTest 源码解读 优化定律 如何扩展前端工具
    14. 14. Web 前端工具 Firefox 阵营  IE 堡垒 ◦ DOM Inspector ◦ IE Developer Toolbar ◦ Firebug ◦ IE Pro ◦ JavaScript Debugger ◦ Fiddler ◦ HTML Validator ◦ HttpWatch ◦ Web Developer ◦ AOL PageTest( 开源 ) ◦ YSlow  通用商业工具 ◦ IBM Page Detailer ◦ HTTP Analyzer
    15. 15. IBM Page Detailer Chart(IE7)
    16. 16. Maximizing Parallel Downloads 1.40 average 36 x 36 px (0.9 Kb) 116 x 61 px (3.4 Kb) 1.20 1.00 0.80response time (seconds) 0.60 0.40 0.20 0.00 1 2 4 5 10 rule of thumb: use at least two but no more than four aliases
    17. 17. IBM Page Detailer details
    18. 18. FireBug Net Panel
    19. 19. YSlow 13 Rules for Fast WebPages_ 网页性能评分以及规则遵循 性
    20. 20. HTTP Analyzer3
    21. 21. AOL PageTest WaterFall View
    22. 22. AOL PageTest OptimiztionCheckList
    23. 23. 在线网页分析websiteoptimization
    24. 24. 性能分析工具小结 FireBug Net PanelIBM Page Detailer  Methodology Methodology ◦ Packet Sniffer ◦ Packet Sniffer  Competitive Advantage Competitive Advantage ◦ Displays waterfall view ◦ Most accurate ◦ Provides HTTP header info ◦ Provides detailed data  Drawbacks ◦ Works for any browser ◦ Runs only in Firefox ◦ Best waterfall view ◦ Inaccurate waterfall view Drawbacks  No render time  No parse time ◦ 90 day free trial  No redirects ◦ Runs only on Windows  No DNS lookups ◦ Misses cached components ◦ Misses cached components AOL PageTest  Methodology YSlow ◦ IE Extension  Methodology ◦ Firefox extension  Competitive Advantage  Competitive Advantage ◦ Open source ◦ performance lint tool ◦ more granular details of each ◦ grades web pages for each rule HTTP request  Drawbacks  Drawbacks ◦ Runs only on IE ◦ Runs only on FireFox
    25. 25.  为什么关注前端性能分析? Yahoo 高性能网页最佳实践 (14+20) 前端性能分析工具 ◦ Fiddler ◦ IBM Page Detailer ◦ FireBug ◦ Yahoo YSlow ◦ HTTP Analyzer ◦ AOL PageTest PageTest 源码解读 优化定律 如何扩展前端工具
    26. 26. DOM ReadyState READYSTATE_UNINITIALIZED ◦ Default initialization state. READYSTATE_LOADING ◦ Object is currently loading its properties. READYSTATE_LOADED ◦ Object has been initialized. – 获取完服务器原始数据,但不 能直接在客户端使用 READYSTATE_INTERACTIVE ◦ Object is interactive, but not all of its data is available. ---- 正在解析数据 READYSTATE_COMPLETE ◦ Object has received all of its data.— 全部数据已解析完客户 端可用的格式
    27. 27. PageTest 源码调试 Microsoft Visual Studio c++ 2008 Win32 Debug IDE BHO 调试参数 : iexplore.exe
    28. 28. WSHook.cpp –winsock2 服务提供者wspStartup = new CAPIHook("msafd.dll", "WSPStartup", (PROC)::WSPStartup_Hook, TRUE);nspStartup = new CAPIHook("rnr20.dll", "NSPStartup", (PROC)::NSPStartup_Hook, TRUE);… // store the original function pointers to use later wsp->socket = lpProcTable->lpWSPSocket; wsp->close = lpProcTable->lpWSPCloseSocket; wsp->connect = lpProcTable->lpWSPConnect; wsp->recv = lpProcTable->lpWSPRecv; wsp->send = lpProcTable->lpWSPSend; wsp->bind = lpProcTable->lpWSPBind; lpProcTable->lpWSPSocket = WSPSocket_Hook; lpProcTable->lpWSPCloseSocket = WSPCloseSocket_Hook; lpProcTable->lpWSPConnect = WSPConnect_Hook; lpProcTable->lpWSPRecv = WSPRecv_Hook; lpProcTable->lpWSPSend = WSPSend_Hook; lpProcTable->lpWSPBind = WSPBind_Hook;
    29. 29. WinInet Hook ( 网络事件 )CWinInetHook::CWinInetHook(void):internetOpenA("wininet.dll", "InternetOpenA", (PROC)::InternetOpenA_Hook, TRUE) , internetOpenW("wininet.dll", "InternetOpenW", (PROC)::InternetOpenW_Hook, TRUE) , internetCloseHandle("wininet.dll", "InternetCloseHandle", (PROC)::InternetCloseHandle_Hook, TRUE) , internetSetStatusCallback("wininet.dll", "InternetSetStatusCallback", (PROC)::InternetSetStatusCallback_Hook, TRUE) , internetSetStatusCallbackA("wininet.dll", "InternetSetStatusCallbackA", (PROC)::InternetSetStatusCallbackA_Hook, TRUE) , internetSetStatusCallbackW("wininet.dll", "InternetSetStatusCallbackW", (PROC)::InternetSetStatusCallbackW_Hook, TRUE) , internetConnectA("wininet.dll", "InternetConnectA", (PROC)::InternetConnectA_Hook, TRUE) , internetConnectW("wininet.dll", "InternetConnectW", (PROC)::InternetConnectW_Hook, TRUE) , internetOpenUrlA("wininet.dll", "InternetOpenUrlA", (PROC)::InternetOpenUrlA_Hook, TRUE) , internetOpenUrlW("wininet.dll", "InternetOpenUrlW", (PROC)::InternetOpenUrlW_Hook, TRUE) , httpOpenRequestA("wininet.dll", "HttpOpenRequestA", (PROC)::HttpOpenRequestA_Hook, TRUE) , httpOpenRequestW("wininet.dll", "HttpOpenRequestW", (PROC)::HttpOpenRequestW_Hook, TRUE) , httpSendRequestA("wininet.dll", "HttpSendRequestA", (PROC)::HttpSendRequestA_Hook, TRUE) , httpSendRequestW("wininet.dll", "HttpSendRequestW", (PROC)::HttpSendRequestW_Hook, TRUE) , ftpOpenFileA("wininet.dll", "FtpOpenFileA", (PROC)::FtpOpenFileA_Hook, TRUE) , ftpOpenFileW("wininet.dll", "FtpOpenFileW", (PROC)::FtpOpenFileW_Hook, TRUE){}
    30. 30. IE BHO 技术
    31. 31. Win32 精确计时QueryPerformanceFrequency((LARGE_INTEGER *)&freq);msFreq = freq / (__int64)1000;…QueryPerformanceCounter((LARGE_INTEGER *)&startRender);
    32. 32. render start time andDocument Complete time the "render start time". This is the point at which the browser first displays any content to the user. the "Document Complete time" which is the time when the browser would fire the onLoad event.
    33. 33. CTestState::CheckRender 判断 render 起点 if( SUCCEEDED(tracker.browser- >get_ReadyState(&rs)) && (rs == READYSTATE_INTERACTIVE || rs == READYSTATE_COMPLETE)){… body2->get_scrollWidth(&width);body2->get_scrollHeight(&height);…} if( width && height ) QueryPerformanceCounter((LARGE_INTEGER *)&startRender);
    34. 34. CWatchDlg::DrawItemWaterfall 画出 render 比例图 const COLORREF colorRender = RGB( 40,188, 0); hPenRender = CreatePen(PS_SOLID, 2, colorRender); rc.DeflateRect(rect.Width() / 4, 0, 2, 0); double width = rc.Width();… double range = (double)(lastRequest - start);…if( startRender && startRender >= start && startRender <= lastRequest) { int x = (int)(((double)(startRender - start) / range) * width); SelectObject(hDC, hPenRender); LineVert(hDC, rc.left + x, rc.top, rc.bottom); }if( !currentDoc && endDoc && endDoc >= start && endDoc <= lastRequest){ int x = (int)(((double)(endDoc - start) / range) * width); SelectObject(hDC, hPenDone); LineVert(hDC, rc.left + x, rc.top, rc.bottom);}
    35. 35. PageTest 优化检查列表
    36. 36. 优化定律 Don’t Optimize Don’t Optimize anything you can’t measure 80/20 rule of Optimization ◦ <20% retriving a typical web page ◦ >80% rendering a typical web page
    37. 37.  为什么关注前端性能分析? Yahoo 高性能网页最佳实践 (14+20) 前端性能分析工具 ◦ Fiddler ◦ IBM Page Detailer ◦ FireBug ◦ Yahoo YSlow ◦ HTTP Analyzer ◦ AOL PageTest PageTest 源码解读 优化定律 如何扩展前端工具
    38. 38. 精减组件利器 Javascript 压缩工具 ◦ YUI Compressor ◦ JSA: 国内开源 ◦ JSMin 图片优化工具 ◦ ImageMagick ◦ Pngcrush : unix/win32 ,开源 ◦ Jpegtran CSS 压缩 ◦ CSSTidy CSS Sprites 图片制作 ◦ CSS Sprite Generator 服务器端压缩 ◦ Apache deflate
    39. 39.  为什么关注前端性能分析? Yahoo 高性能网页最佳实践 (14+20) 前端性能分析工具 ◦ Fiddler ◦ IBM Page Detailer ◦ FireBug ◦ Yahoo YSlow ◦ HTTP Analyzer ◦ AOL PageTest PageTest 源码解读 优化定律 如何扩展前端工具
    40. 40. 如何扩展前端分析工具 建立持续网页评估结果库及告警机制 ◦ 集成 YSlow 接口? ◦ 扩充新 20 条? 建立持续网页速率监控池 ◦ 扩展 PageTest ◦ 自主研发 BHO 工具 ◦ Apache module 推送 document.readyState 事件代码 ◦ …
    41. 41. Books
    42. 42. Links poolExceptional Performance: http:// performance.corp.yahoo.comYSlow?: http:// performance.corp.yahoo.com/docs/yslow.htmlIBM Page Detailer: http://alphaworks.ibm.com/tech/pagedetailerAOL Pagetest http://sourceforge.net/projects/pagetest/
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×