KEMBAR78
Analyzing the Performance of Mobile Web | PDF
Analyzing the Performance of
        Mobile Web:
 Challenges and Techniques

                 ARIYA HIDAYAT
              ENGINEERING DIRECTOR
whoami
Going Under the Hood
MyOwnSlow
Overview
Performance Areas

     Network



               Graphics


                          JavaScript
Desktop Tools

          Web Inspector      Page Speed     WebMetrics

Firebug       Speed Tracer                YSlow
                             Blaze.io
 dynaTrace       pcapperf           WebPageTest
Mobile Situation
      Metrics                                     Continous Integration
      •framerate
      •bytes transferred
      •caching
      •cookies
      •cache manifest
      •code size
      •execution speed

                Network Variances
                     2G, EDGE, 3G, 4G, LTE, ...
“Too Many Phones Will Kill You...”
Stake Holders         Web Site Developers

                                            Service
                                            Provider


                  Application Developers
Browser vendors
Approaches                               High-speed
                         Benchmark         Camera



      Inject                               RF Monitor
instrumentation                 Proxy
                                           Remote
          Read the                        inspection
         source code


        Intrusive      Emulation        Observation
Strategies
                                 Reducing complexity


      1      Replicate and/or analyze on desktop



       2     Tweak and insert instrumentation

                            System level
Caveats

   Concept




             Focus
Tools of Trade




               Nexus One          Gingerbread


       http://source.android.com/source/building-devices.html
Headless WebKit

                   “Full web stack.
                 No browser required”




   http://www.phantomjs.org   https://github.com/ariya/phantomjs
Source Code

     WebKit              http://www.webkit.org/

            http://android.git.kernel.org/?p=platform/external/webkit.git
            http://opensource.apple.com/



       V8         http://code.google.com/p/v8/
WebCore
Di erent WebKit “Ports”                               graphics

                       Mac       Chromium
GraphicsContext        iOS        Android            Qt     Gtk


                                   Skia                      Cairo
                  CoreGraphics
                                                 QPainter


                                          graphics stack
Network
“Understanding Mobile Web Browser Performance”
         Rajiv Vijayakumar (Qualcomm)



 Wed 2:40 pm, Ballroom ABCD
Web Inspector Network
http://www.softwareishard.com/blog/har-12-spec/



HTTP Archive (HAR)
Automating Network Sni ng (Desktop)


      phantomjs netsniff.js http://m.bing.com




          Visualize using online HAR viewer
Android WebKit + Network Stack

Java      Browser

                                            Network Stack   Java
               WebView
   Java

                         libwebcore   JNI
              C++
Real-time Sni ng + Postprocessing

 WebFrame::startLoadingResource             WebCoreResourceLoader::AddData(...)



                                  waiting           data transfer


                                                WebCoreResourceLoader::Finished()
Example: Orchid
     adb logcat -v time | startLoadingResource NETWORK
06-12 22:57:48.430 D/webcoreglue( 1357):
                                         grep NETWORK                           0x66d368 http://en.m.wikipedia.org/wiki/
Orchid
06-12 22:57:48.710 D/webcoreglue(   1357): ReceivedResponse NETWORK handle=0x66d368 mimeType=text/html url=http://
en.m.wikipedia.org/wiki/Orchid
06-12 22:57:48.780 D/webcoreglue(   1357): startLoadingResource NETWORK 0x6a8678 http://en.m.wikipedia.org/
stylesheets/android.css
06-12 22:57:48.780 D/webcoreglue(   1357): startLoadingResource NETWORK 0x6ab388 http://en.m.wikipedia.org/
javascripts/jquery.js
06-12 22:57:48.790 D/webcoreglue(   1357): startLoadingResource NETWORK 0x6ab7e8 http://en.m.wikipedia.org/
javascripts/application.js
06-12 22:57:48.790 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   4162 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:48.790 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   8192 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:48.790 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   1361 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:48.980 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   8192 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:48.980 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   803 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:49.000 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   4702 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:49.000 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   4507 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:49.020 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   8192 http://en.m.wikipedia.org/wiki/Orchid
06-12 22:57:49.050 D/webcoreglue(   1357):   AddData   NETWORK   0x66d368   6750 http://en.m.wikipedia.org/wiki/Orchid
Example: Orchid
Going O ine: Cache Manifest
                                     Automatic local
                                  storage optimization

    phantomjs confess.js http://functionsource.com




           https://github.com/jamesgpearce/confess
Graphics
Drawing Command Analysis
       WebCore                       Log file
       graphics


                  GraphicsContext


                              Skia
Example: Bing
  platformInit
  savePlatformState
  translate 0,0
  translate 0,0
  clip 1,0 0x6.95322e-310
  fillRect 0,0 800x556 color   ff ff ff ff
  restorePlatformState
  platformDestroy
  platformInit
  savePlatformState
  translate 0,0
  translate 0,0
  clip 1,0 0x6.95322e-310
  fillRect 0,0 800x556 color   ff ff ff ff
  restorePlatformState
  platformDestroy
  platformInit
  savePlatformState
  translate 0,0
  translate 0,0
  clip 1,0 0x6.95322e-310
  fillRect 0,0 800x556 color   ff ff ff ff
  fillRect 0,0 800x556 color   ff ff ff ff
Painting Traces
Display List Approach
                                  no overhead
      WebKit                       anymore


               GraphicsContext
                                          “SkPicture”
                           Skia
How Fast is the “Playback”?
      #include "TimeCounter.h"


      bool WebViewCore::drawContent(SkCanvas* canvas, SkColor)
      {
          uint32_t timestamp = getThreadMsec();

          .... painting code ....

          DBG_SET_LOGD("% ms", getThreadMsec() - timestamp);
      }


          external/webkit/WebKit/android/jni/WebViewCore.cpp
Example: Google News
 adb logcat -v time | grep drawContent
     16:24:04.070   D/webcoreglue(    273):   drawContent   11   ms
     16:24:04.110   D/webcoreglue(    273):   drawContent   13   ms
     16:24:04.150   D/webcoreglue(    273):   drawContent   13   ms
     16:24:04.190   D/webcoreglue(    273):   drawContent   10   ms
     16:24:04.240   D/webcoreglue(    273):   drawContent   10   ms
     16:24:04.280   D/webcoreglue(    273):   drawContent   13   ms
     16:24:04.320   D/webcoreglue(    273):   drawContent   13   ms
     16:24:04.360   D/webcoreglue(    273):   drawContent   13   ms
     16:24:06.080   D/webcoreglue(    273):   drawContent   12   ms
     16:24:06.140   D/webcoreglue(    273):   drawContent   10   ms
     16:24:06.180   D/webcoreglue(    273):   drawContent   13   ms
     16:24:06.230   D/webcoreglue(    273):   drawContent   14   ms
     16:24:06.600   D/webcoreglue(    273):   drawContent   26   ms
     16:24:06.640   D/webcoreglue(    273):   drawContent   13   ms
     16:24:06.860   D/webcoreglue(    273):   drawContent   33   ms
     16:24:06.890   D/webcoreglue(    273):   drawContent   12   ms
     16:24:06.930   D/webcoreglue(    273):   drawContent   13   ms
     16:24:06.960   D/webcoreglue(    273):   drawContent   13   ms
     16:24:07.000   D/webcoreglue(    273):   drawContent   13   ms
How Much is the Frame Rate?
   bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color)
   {
      static uint32_t frame_ref = 0;
      static int frame_tick = 0;

       ... painting code ...

       frame_tick++;
       if (frame_tick >= 10) {
           DBG_SET_LOGD("framerate %d fps", (int)(frame_tick * 1000 /
               (1 + getThreadMsec() - frame_ref)));
           frame_tick = 0;
           frame_ref = getThreadMsec();
       }
   }
Site Mirroring                                        Intertubes

                       port 8080
                                                     SQLite DB
                            Proxy


                            Mirror

                        port 8081

      https://github.com/ariya/X2    network/netspiegel
JavaScript
http://www.sencha.com/blog/remote-javascript-debugging-on-android/



Remote Console




          http://github.com/senchalabs/android-tools
Garbage Collector
   bool Heap::CollectGarbage(int requested_size, AllocationSpace space)
   {
       .. some code ...

       PerformGarbageCollection(space, collector, &tracer);
       LOGD("PerformGarbageCollection %d", requested_size);

       .. some code ...
   }




                          external/v8/src/heap.cc
Example: Travelmate
adb logcat -v time | grep GarbageCollection

  06-13   13:24:36.470   D/v8            (    532):   PerformGarbageCollection   20
  06-13   13:24:36.630   D/v8            (    532):   PerformGarbageCollection   32788
  06-13   13:24:36.740   D/v8            (    532):   PerformGarbageCollection   116
  06-13   13:24:36.810   D/v8            (    532):   PerformGarbageCollection   88
  06-13   13:24:36.870   D/v8            (    532):   PerformGarbageCollection   52
  06-13   13:24:37.000   D/v8            (    532):   PerformGarbageCollection   20
  06-13   13:24:37.090   D/v8            (    532):   PerformGarbageCollection   24
  06-13   13:24:37.450   D/v8            (    532):   PerformGarbageCollection   35884
  06-13   13:24:39.400   D/v8            (    532):   PerformGarbageCollection   20
  06-13   13:24:39.730   D/v8            (    532):   PerformGarbageCollection   3392
Keyword vs Identifier
     instanceof            instanceComponent


                                requires
                                checking
                                 9 chars



                  a g h j klmopqxyz
Function Parsing
                                     Analyze the syntax
       foobar = function(x, y, z)
                                     Mark the position of
       {                              function ‘foobar’
       ....
       }

       foobar(x, y, z);

               Compile and run the
                function ‘foobar’
Static Code Analysis
          hammerjs --syntax source-file.js


                            JSON syntax tree


                 Reflect.parse(code)



          https://github.com/senchalabs/hammerjs
Syntax Tree
                                    Variable Declaration
   identifier        number

var answer = 42;
keyword        equal sign    Identifier
                                                           Literal Constant


                             answer                            42
"type": "IfStatement",
                     "test": {
                                 "type": "BinaryExpression",
                                 "operator": "==",
                                 "left": {
                                     "type": "Identifier",
                                     "name": "x"
                                 },
                                 "right": {
                                     "type": "Identifier",
                                     "name": "y"
                                 }
if (x == y) foo();           },
                             "consequent": {
                                 "type": "ExpressionStatement",
                                 "expression": {
                                     "type": "CallExpression",
       Danger!                       "callee": {
                                         "type": "Identifier",
                                         "name": "foo"
                                     },
                                     "arguments": []
                                 }
                             },
                             "alternate": null
Deploy-time Pruning
                                        Never used

        function createList(position, options) {
           ... some code ...
        }

        createList({ x: 0, y: 0});
        createList({ x: 0, y: 100});
Avoid Object Construction
              Create + Destroy

startTime = new Date();               startTime = Date.now();
// heavy processing                   // heavy processing
elapsed = (new Date()) - startTime;   elapsed = Date.now() - startTime;
Irrelevant Platforms
                             Does not apply in Mobile

      if (typeof object.attachEvent !== 'undefined') {
          // Internet Explorer < 9
          object.attachEvent('on'+ev, createWrapper(func));
      } else {
          // DOM Level 3
          object.addEventListener(ev, func);
      }
User Interactions
http://www.sencha.com/blog/event-recorder-for-android-web-applications/




Event Recorder & Player
Conclusion
Today
     Replicate and analyze on desktop
Find, look at, and understand the source code
Tweak at the system level + post-processing
Future
More built-in instrumentation
     Remote inspection
   API for test automation
THANK YOU!

         ariya.hidayat@gmail.com


         ariya.blogspot.com


         @ariyahidayat

Analyzing the Performance of Mobile Web

  • 1.
    Analyzing the Performanceof Mobile Web: Challenges and Techniques ARIYA HIDAYAT ENGINEERING DIRECTOR
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
    Performance Areas Network Graphics JavaScript
  • 7.
    Desktop Tools Web Inspector Page Speed WebMetrics Firebug Speed Tracer YSlow Blaze.io dynaTrace pcapperf WebPageTest
  • 8.
    Mobile Situation Metrics Continous Integration •framerate •bytes transferred •caching •cookies •cache manifest •code size •execution speed Network Variances 2G, EDGE, 3G, 4G, LTE, ...
  • 9.
    “Too Many PhonesWill Kill You...”
  • 10.
    Stake Holders Web Site Developers Service Provider Application Developers Browser vendors
  • 11.
    Approaches High-speed Benchmark Camera Inject RF Monitor instrumentation Proxy Remote Read the inspection source code Intrusive Emulation Observation
  • 12.
    Strategies Reducing complexity 1 Replicate and/or analyze on desktop 2 Tweak and insert instrumentation System level
  • 13.
    Caveats Concept Focus
  • 14.
    Tools of Trade Nexus One Gingerbread http://source.android.com/source/building-devices.html
  • 15.
    Headless WebKit “Full web stack. No browser required” http://www.phantomjs.org https://github.com/ariya/phantomjs
  • 16.
    Source Code WebKit http://www.webkit.org/ http://android.git.kernel.org/?p=platform/external/webkit.git http://opensource.apple.com/ V8 http://code.google.com/p/v8/
  • 17.
    WebCore Di erent WebKit“Ports” graphics Mac Chromium GraphicsContext iOS Android Qt Gtk Skia Cairo CoreGraphics QPainter graphics stack
  • 18.
  • 19.
    “Understanding Mobile WebBrowser Performance” Rajiv Vijayakumar (Qualcomm) Wed 2:40 pm, Ballroom ABCD
  • 20.
  • 21.
  • 22.
    Automating Network Sning (Desktop) phantomjs netsniff.js http://m.bing.com Visualize using online HAR viewer
  • 23.
    Android WebKit +Network Stack Java Browser Network Stack Java WebView Java libwebcore JNI C++
  • 24.
    Real-time Sni ng+ Postprocessing WebFrame::startLoadingResource WebCoreResourceLoader::AddData(...) waiting data transfer WebCoreResourceLoader::Finished()
  • 25.
    Example: Orchid adb logcat -v time | startLoadingResource NETWORK 06-12 22:57:48.430 D/webcoreglue( 1357): grep NETWORK 0x66d368 http://en.m.wikipedia.org/wiki/ Orchid 06-12 22:57:48.710 D/webcoreglue( 1357): ReceivedResponse NETWORK handle=0x66d368 mimeType=text/html url=http:// en.m.wikipedia.org/wiki/Orchid 06-12 22:57:48.780 D/webcoreglue( 1357): startLoadingResource NETWORK 0x6a8678 http://en.m.wikipedia.org/ stylesheets/android.css 06-12 22:57:48.780 D/webcoreglue( 1357): startLoadingResource NETWORK 0x6ab388 http://en.m.wikipedia.org/ javascripts/jquery.js 06-12 22:57:48.790 D/webcoreglue( 1357): startLoadingResource NETWORK 0x6ab7e8 http://en.m.wikipedia.org/ javascripts/application.js 06-12 22:57:48.790 D/webcoreglue( 1357): AddData NETWORK 0x66d368 4162 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:48.790 D/webcoreglue( 1357): AddData NETWORK 0x66d368 8192 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:48.790 D/webcoreglue( 1357): AddData NETWORK 0x66d368 1361 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:48.980 D/webcoreglue( 1357): AddData NETWORK 0x66d368 8192 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:48.980 D/webcoreglue( 1357): AddData NETWORK 0x66d368 803 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:49.000 D/webcoreglue( 1357): AddData NETWORK 0x66d368 4702 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:49.000 D/webcoreglue( 1357): AddData NETWORK 0x66d368 4507 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:49.020 D/webcoreglue( 1357): AddData NETWORK 0x66d368 8192 http://en.m.wikipedia.org/wiki/Orchid 06-12 22:57:49.050 D/webcoreglue( 1357): AddData NETWORK 0x66d368 6750 http://en.m.wikipedia.org/wiki/Orchid
  • 26.
  • 27.
    Going O ine:Cache Manifest Automatic local storage optimization phantomjs confess.js http://functionsource.com https://github.com/jamesgpearce/confess
  • 28.
  • 29.
    Drawing Command Analysis WebCore Log file graphics GraphicsContext Skia
  • 30.
    Example: Bing platformInit savePlatformState translate 0,0 translate 0,0 clip 1,0 0x6.95322e-310 fillRect 0,0 800x556 color ff ff ff ff restorePlatformState platformDestroy platformInit savePlatformState translate 0,0 translate 0,0 clip 1,0 0x6.95322e-310 fillRect 0,0 800x556 color ff ff ff ff restorePlatformState platformDestroy platformInit savePlatformState translate 0,0 translate 0,0 clip 1,0 0x6.95322e-310 fillRect 0,0 800x556 color ff ff ff ff fillRect 0,0 800x556 color ff ff ff ff
  • 31.
  • 32.
    Display List Approach no overhead WebKit anymore GraphicsContext “SkPicture” Skia
  • 33.
    How Fast isthe “Playback”? #include "TimeCounter.h" bool WebViewCore::drawContent(SkCanvas* canvas, SkColor) { uint32_t timestamp = getThreadMsec(); .... painting code .... DBG_SET_LOGD("% ms", getThreadMsec() - timestamp); } external/webkit/WebKit/android/jni/WebViewCore.cpp
  • 34.
    Example: Google News adb logcat -v time | grep drawContent 16:24:04.070 D/webcoreglue(  273): drawContent 11 ms 16:24:04.110 D/webcoreglue(  273): drawContent 13 ms 16:24:04.150 D/webcoreglue(  273): drawContent 13 ms 16:24:04.190 D/webcoreglue(  273): drawContent 10 ms 16:24:04.240 D/webcoreglue(  273): drawContent 10 ms 16:24:04.280 D/webcoreglue(  273): drawContent 13 ms 16:24:04.320 D/webcoreglue(  273): drawContent 13 ms 16:24:04.360 D/webcoreglue(  273): drawContent 13 ms 16:24:06.080 D/webcoreglue(  273): drawContent 12 ms 16:24:06.140 D/webcoreglue(  273): drawContent 10 ms 16:24:06.180 D/webcoreglue(  273): drawContent 13 ms 16:24:06.230 D/webcoreglue(  273): drawContent 14 ms 16:24:06.600 D/webcoreglue(  273): drawContent 26 ms 16:24:06.640 D/webcoreglue(  273): drawContent 13 ms 16:24:06.860 D/webcoreglue(  273): drawContent 33 ms 16:24:06.890 D/webcoreglue(  273): drawContent 12 ms 16:24:06.930 D/webcoreglue(  273): drawContent 13 ms 16:24:06.960 D/webcoreglue(  273): drawContent 13 ms 16:24:07.000 D/webcoreglue(  273): drawContent 13 ms
  • 35.
    How Much isthe Frame Rate? bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color) { static uint32_t frame_ref = 0; static int frame_tick = 0; ... painting code ... frame_tick++; if (frame_tick >= 10) { DBG_SET_LOGD("framerate %d fps", (int)(frame_tick * 1000 / (1 + getThreadMsec() - frame_ref))); frame_tick = 0; frame_ref = getThreadMsec(); } }
  • 36.
    Site Mirroring Intertubes port 8080 SQLite DB Proxy Mirror port 8081 https://github.com/ariya/X2 network/netspiegel
  • 37.
  • 38.
  • 40.
    Garbage Collector bool Heap::CollectGarbage(int requested_size, AllocationSpace space) { .. some code ... PerformGarbageCollection(space, collector, &tracer); LOGD("PerformGarbageCollection %d", requested_size); .. some code ... } external/v8/src/heap.cc
  • 41.
    Example: Travelmate adb logcat-v time | grep GarbageCollection 06-13 13:24:36.470 D/v8      (  532): PerformGarbageCollection 20 06-13 13:24:36.630 D/v8      (  532): PerformGarbageCollection 32788 06-13 13:24:36.740 D/v8      (  532): PerformGarbageCollection 116 06-13 13:24:36.810 D/v8      (  532): PerformGarbageCollection 88 06-13 13:24:36.870 D/v8      (  532): PerformGarbageCollection 52 06-13 13:24:37.000 D/v8      (  532): PerformGarbageCollection 20 06-13 13:24:37.090 D/v8      (  532): PerformGarbageCollection 24 06-13 13:24:37.450 D/v8      (  532): PerformGarbageCollection 35884 06-13 13:24:39.400 D/v8      (  532): PerformGarbageCollection 20 06-13 13:24:39.730 D/v8      (  532): PerformGarbageCollection 3392
  • 42.
    Keyword vs Identifier instanceof instanceComponent requires checking 9 chars a g h j klmopqxyz
  • 43.
    Function Parsing Analyze the syntax foobar = function(x, y, z) Mark the position of { function ‘foobar’ .... } foobar(x, y, z); Compile and run the function ‘foobar’
  • 44.
    Static Code Analysis hammerjs --syntax source-file.js JSON syntax tree Reflect.parse(code) https://github.com/senchalabs/hammerjs
  • 45.
    Syntax Tree Variable Declaration identifier number var answer = 42; keyword equal sign Identifier Literal Constant answer 42
  • 46.
    "type": "IfStatement", "test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "x" }, "right": { "type": "Identifier", "name": "y" } if (x == y) foo(); }, "consequent": { "type": "ExpressionStatement", "expression": { "type": "CallExpression", Danger! "callee": { "type": "Identifier", "name": "foo" }, "arguments": [] } }, "alternate": null
  • 47.
    Deploy-time Pruning Never used function createList(position, options) { ... some code ... } createList({ x: 0, y: 0}); createList({ x: 0, y: 100});
  • 48.
    Avoid Object Construction Create + Destroy startTime = new Date(); startTime = Date.now(); // heavy processing // heavy processing elapsed = (new Date()) - startTime; elapsed = Date.now() - startTime;
  • 49.
    Irrelevant Platforms Does not apply in Mobile if (typeof object.attachEvent !== 'undefined') { // Internet Explorer < 9 object.attachEvent('on'+ev, createWrapper(func)); } else { // DOM Level 3 object.addEventListener(ev, func); }
  • 50.
  • 51.
  • 52.
  • 53.
    Today Replicate and analyze on desktop Find, look at, and understand the source code Tweak at the system level + post-processing
  • 54.
    Future More built-in instrumentation Remote inspection API for test automation
  • 55.
    THANK YOU! ariya.hidayat@gmail.com ariya.blogspot.com @ariyahidayat