Design Tips for
Dynamic UIs Under
   Heavy Load

        Patrick Lightbody
      Founder, BrowserMob
    patrick@browsermob.com


                 http://browsermob.com
Patrick & the ‘Mob
Open source contributor
-   Apache Struts 2.0 (previously WebWork)

-   Founder of OpenQA.org and SeleniumHQ.org

-   Creator of Selenium Remote Control

Founder of BrowserMob
-   On-demand load testing and monitoring services

-   Uses real web browsers in various cloud
    environments (EC2, GoGrid, Rackspace, etc)


                           http://browsermob.com
The Problem
AJAX => Faster (Perceived) Experience
-   More logic on front-end with asynchronous calls
    to server logic on back-end

But when the back-end is slow or error
prone, the experience tends to be worse
-   Non AJAX => Full page load => spinning “e” for IE

Most complex UIs built in isolation
-   Tested on localhost (no load, infinite bandwidth)


                             http://browsermob.com
Recent Example
Load test for a UK-based car insurance
provider
Frequent errors in which the the browser
was showing a registration form claiming
that field X was not filled out
A real head-scratcher... we were 110%
positive that field was being filled out by
the test
Finally figured it out: reproduced by hand

                        http://browsermob.com
UI Design
 First Name     Patrick                     First Name    Patrick

 Last Name      Lightbody                   Last Name     Lightbody

  Company       BrowserMob                   Company      BrowserMob

     Email                                      Email     Email is required

Home Phone      4158305488              Home Phone        (415) 830-5488

 Cell Phone                                 Cell Phone



                onchange
                                                   inject form data back in

                  Form                                       Form
              Representation                             Representation
                 (JSON)                                     (JSON)



                               Web Server



                                        http://browsermob.com
Typical Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email


Home Phone


 Cell Phone




                           http://browsermob.com
Typical Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone


 Cell Phone




                                   http://browsermob.com
Typical Sequence
                                       AJAX Request #1
 First Name   Patrick

                                                Form
 Last Name    Lightbody                     Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Typical Sequence
                                       AJAX Request #1
 First Name   Patrick

                                                Form
 Last Name    Lightbody                     Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Typical Sequence
                                       AJAX Request #1
 First Name   Patrick

                                                Form
 Last Name    Lightbody                     Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Typical Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone


 Cell Phone




                                   http://browsermob.com
Typical Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    4158305488

 Cell Phone




                                   http://browsermob.com
Typical Sequence
                                       AJAX Request #2
 First Name   Patrick

                                                Form
 Last Name    Lightbody                     Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    4158305488
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Typical Sequence
                                       AJAX Request #2
 First Name   Patrick

                                                Form
 Last Name    Lightbody                     Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    4158305488
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Typical Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    (415) 830-5488

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email


Home Phone


 Cell Phone




                           http://browsermob.com
Problem Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone


 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick
                                        AJAX Request #1
 Last Name    Lightbody                         Form
                                            Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone


 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    4158305488

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick
                                        AJAX Request #2
 Last Name    Lightbody                         Form
                                            Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    4158305488
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick
                                        AJAX Request #2
 Last Name    Lightbody                         Form
                                            Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    4158305488
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick

 Last Name    Lightbody

  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    (415) 830-5488

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick
                                        AJAX Request #1
 Last Name    Lightbody                         Form
                                            Representation
                                               (JSON)
  Company     BrowserMob

     Email    patrick@browsermob

Home Phone    (415) 830-5488
                                             Web Server

 Cell Phone




                                   http://browsermob.com
Problem Sequence
 First Name   Patrick

 Last Name    Lightbody
                                           Whoops!
  Company     BrowserMob

     Email    patrick@browsermob    No more Home Phone!
Home Phone    (415) 830-5488

 Cell Phone




                                   http://browsermob.com
Reproducing
Re-create the slowdown/error in your code
-   Can be turned on/off with a “test” flag in your app

Run load tests simultaneously with
browser tests
-   Run a Selenium test on loop while using JMeter

Run your browser through a network
simulator
-   Simulate bandwidth, latency, response codes, etc


                              http://browsermob.com
Mocking out Failure
Add simple if statement in the server code
that sleep for X seconds or throw an error
Attach a debugger, break on a line, and just
sit there before you resume execution
If you’re feeling especially adventurous,
make a generic “filter” for your app
-   In Java this would be a “Servlet Filter”

-   Could be made very advanced


                              http://browsermob.com
public void doFilter(HttpServletRequest req,
                     HttpServletResponse res,
                     FilterChain chain)
        throws IOException, ServletException {

    String uri = req.getRequestURI();

    Random r = new Random();
    if (r.nextInt(100) > 80) {
        res.sendError(500, "20% chance of failure!");
        return;
    }

    // sleep between 0 and 5 seconds
    Thread.sleep(r.nextInt(1000) * 5);

    chain.doFilter(req, res);

}


                                http://browsermob.com
Selenium During Load
Hard to predict all ways in which things can
go wrong
-   Easier to simulate the ways things should go right

Run a standard load test against the REST
interfaces
-   Ideally, this should “realistically” slow them down

Simultaneously, play back Selenium scripts
-   Check for functionality over performance


                              http://browsermob.com
Selenium as Load
Similar approach as before, but on steroids
Run hundreds or thousands of Selenium
scripts in parallel
-   This means you need hundreds or thousands of
    browsers!

-   Checking performance and functionality
    concurrently

Produces hyper-realistic load scenarios
and almost always uncovers unexpected
problems
                            http://browsermob.com
How It Works




      http://browsermob.com
How It Works


     Automatically provision
    browsers from the cloud




         http://browsermob.com
How It Works


     Automatically provision
    browsers from the cloud




         http://browsermob.com
How It Works
4000 CPU Cores
 3.5TB of RAM


                  Automatically provision
                 browsers from the cloud




                      http://browsermob.com
Network Simulators
Another approach is to run your browser
through a network simulator
Usually done via an HTTP proxy that can be
tuned to:
-   Return fake error codes

-   Simulate bandwidth & latency

-   Drop packets

-   Record network performance


                              http://browsermob.com
Charles Proxy
Charles Proxy
-   “Web Debugging Proxy Application”

-   Windows, OS X, and Linux

-   Cost: $50 per user w/ bulk discounts

-   http://www.charlesproxy.com




                             http://browsermob.com
BrowserMob Proxy
Announcing today: free, open source utility
Supports HTTP and HTTPS
Produces Firebug-like results for any
browser
Simulates different bandwidth, latency, and
error conditions
Available for download today!
-   http://proxy.browsermob.com

                           http://browsermob.com
Demo




  http://browsermob.com
Design Tips




      http://browsermob.com
Design for Failure
Never forget: AJAX is still a network call
-   Networks fail for a lot of different reasons

-   Networks can be unpredictable (ie: request #1 can
    take longer than request #2)

Add hooks to AJAX requests for the
unexpected
-   Write your code to store request params & retry

Test for failure too!


                              http://browsermob.com
Be Careful w/ DOM
Only change the DOM state if it’s absolutely
necessary
-   Avoid aggressive “synchronization” common in
    some AJAX toolkits (ex: our form sync example)

Merge data together rather than replace
-   Partial page loads (div.innerHTML = ...) is also bad

-   Involves more work, but results in a much better
    experience when things don’t work well



                              http://browsermob.com
Lock the UI
Don’t give the user a chance to change
things that might also get changed by you
-   In our form example: disable the form elements!

-   If necessary, use a modal dialog box to lock the
    entire UI

But remember: have a recovery plan!
-   Test for failure and ensure that the UI unlocks
    when unexpected behavior occurs



                              http://browsermob.com
Inform the User
Always keep the user informed about what
is happening
Ideally give them an “escape hatch” if
things go terrible wrong
-   Set thresholds for when to present the escape
    hatch

-   GMail is a good example of this

At minimum, simple “loading” indicator


                             http://browsermob.com
http://browsermob.com
Questions?
       Patrick Lightbody
     Founder, BrowserMob
   patrick@browsermob.com

BrowserMob Proxy (Open Source)
  http://proxy.browsermob.com

    BrowserMob Services
    http://browsermob.com



                 http://browsermob.com

Patrick Lightbody Presentation Tae Slides

  • 1.
    Design Tips for DynamicUIs Under Heavy Load Patrick Lightbody Founder, BrowserMob patrick@browsermob.com http://browsermob.com
  • 2.
    Patrick & the‘Mob Open source contributor - Apache Struts 2.0 (previously WebWork) - Founder of OpenQA.org and SeleniumHQ.org - Creator of Selenium Remote Control Founder of BrowserMob - On-demand load testing and monitoring services - Uses real web browsers in various cloud environments (EC2, GoGrid, Rackspace, etc) http://browsermob.com
  • 3.
    The Problem AJAX =>Faster (Perceived) Experience - More logic on front-end with asynchronous calls to server logic on back-end But when the back-end is slow or error prone, the experience tends to be worse - Non AJAX => Full page load => spinning “e” for IE Most complex UIs built in isolation - Tested on localhost (no load, infinite bandwidth) http://browsermob.com
  • 4.
    Recent Example Load testfor a UK-based car insurance provider Frequent errors in which the the browser was showing a registration form claiming that field X was not filled out A real head-scratcher... we were 110% positive that field was being filled out by the test Finally figured it out: reproduced by hand http://browsermob.com
  • 5.
    UI Design FirstName Patrick First Name Patrick Last Name Lightbody Last Name Lightbody Company BrowserMob Company BrowserMob Email Email Email is required Home Phone 4158305488 Home Phone (415) 830-5488 Cell Phone Cell Phone onchange inject form data back in Form Form Representation Representation (JSON) (JSON) Web Server http://browsermob.com
  • 6.
    Typical Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email Home Phone Cell Phone http://browsermob.com
  • 7.
    Typical Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone Cell Phone http://browsermob.com
  • 8.
    Typical Sequence AJAX Request #1 First Name Patrick Form Last Name Lightbody Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone Web Server Cell Phone http://browsermob.com
  • 9.
    Typical Sequence AJAX Request #1 First Name Patrick Form Last Name Lightbody Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone Web Server Cell Phone http://browsermob.com
  • 10.
    Typical Sequence AJAX Request #1 First Name Patrick Form Last Name Lightbody Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone Web Server Cell Phone http://browsermob.com
  • 11.
    Typical Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone Cell Phone http://browsermob.com
  • 12.
    Typical Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone 4158305488 Cell Phone http://browsermob.com
  • 13.
    Typical Sequence AJAX Request #2 First Name Patrick Form Last Name Lightbody Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone 4158305488 Web Server Cell Phone http://browsermob.com
  • 14.
    Typical Sequence AJAX Request #2 First Name Patrick Form Last Name Lightbody Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone 4158305488 Web Server Cell Phone http://browsermob.com
  • 15.
    Typical Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone (415) 830-5488 Cell Phone http://browsermob.com
  • 16.
    Problem Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email Home Phone Cell Phone http://browsermob.com
  • 17.
    Problem Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone Cell Phone http://browsermob.com
  • 18.
    Problem Sequence FirstName Patrick AJAX Request #1 Last Name Lightbody Form Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone Web Server Cell Phone http://browsermob.com
  • 19.
    Problem Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone Cell Phone http://browsermob.com
  • 20.
    Problem Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone 4158305488 Cell Phone http://browsermob.com
  • 21.
    Problem Sequence FirstName Patrick AJAX Request #2 Last Name Lightbody Form Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone 4158305488 Web Server Cell Phone http://browsermob.com
  • 22.
    Problem Sequence FirstName Patrick AJAX Request #2 Last Name Lightbody Form Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone 4158305488 Web Server Cell Phone http://browsermob.com
  • 23.
    Problem Sequence FirstName Patrick Last Name Lightbody Company BrowserMob Email patrick@browsermob Home Phone (415) 830-5488 Cell Phone http://browsermob.com
  • 24.
    Problem Sequence FirstName Patrick AJAX Request #1 Last Name Lightbody Form Representation (JSON) Company BrowserMob Email patrick@browsermob Home Phone (415) 830-5488 Web Server Cell Phone http://browsermob.com
  • 25.
    Problem Sequence FirstName Patrick Last Name Lightbody Whoops! Company BrowserMob Email patrick@browsermob No more Home Phone! Home Phone (415) 830-5488 Cell Phone http://browsermob.com
  • 26.
    Reproducing Re-create the slowdown/errorin your code - Can be turned on/off with a “test” flag in your app Run load tests simultaneously with browser tests - Run a Selenium test on loop while using JMeter Run your browser through a network simulator - Simulate bandwidth, latency, response codes, etc http://browsermob.com
  • 27.
    Mocking out Failure Addsimple if statement in the server code that sleep for X seconds or throw an error Attach a debugger, break on a line, and just sit there before you resume execution If you’re feeling especially adventurous, make a generic “filter” for your app - In Java this would be a “Servlet Filter” - Could be made very advanced http://browsermob.com
  • 28.
    public void doFilter(HttpServletRequestreq, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { String uri = req.getRequestURI(); Random r = new Random(); if (r.nextInt(100) > 80) { res.sendError(500, "20% chance of failure!"); return; } // sleep between 0 and 5 seconds Thread.sleep(r.nextInt(1000) * 5); chain.doFilter(req, res); } http://browsermob.com
  • 29.
    Selenium During Load Hardto predict all ways in which things can go wrong - Easier to simulate the ways things should go right Run a standard load test against the REST interfaces - Ideally, this should “realistically” slow them down Simultaneously, play back Selenium scripts - Check for functionality over performance http://browsermob.com
  • 30.
    Selenium as Load Similarapproach as before, but on steroids Run hundreds or thousands of Selenium scripts in parallel - This means you need hundreds or thousands of browsers! - Checking performance and functionality concurrently Produces hyper-realistic load scenarios and almost always uncovers unexpected problems http://browsermob.com
  • 31.
    How It Works http://browsermob.com
  • 32.
    How It Works Automatically provision browsers from the cloud http://browsermob.com
  • 33.
    How It Works Automatically provision browsers from the cloud http://browsermob.com
  • 34.
    How It Works 4000CPU Cores 3.5TB of RAM Automatically provision browsers from the cloud http://browsermob.com
  • 35.
    Network Simulators Another approachis to run your browser through a network simulator Usually done via an HTTP proxy that can be tuned to: - Return fake error codes - Simulate bandwidth & latency - Drop packets - Record network performance http://browsermob.com
  • 36.
    Charles Proxy Charles Proxy - “Web Debugging Proxy Application” - Windows, OS X, and Linux - Cost: $50 per user w/ bulk discounts - http://www.charlesproxy.com http://browsermob.com
  • 37.
    BrowserMob Proxy Announcing today:free, open source utility Supports HTTP and HTTPS Produces Firebug-like results for any browser Simulates different bandwidth, latency, and error conditions Available for download today! - http://proxy.browsermob.com http://browsermob.com
  • 38.
  • 39.
    Design Tips http://browsermob.com
  • 40.
    Design for Failure Neverforget: AJAX is still a network call - Networks fail for a lot of different reasons - Networks can be unpredictable (ie: request #1 can take longer than request #2) Add hooks to AJAX requests for the unexpected - Write your code to store request params & retry Test for failure too! http://browsermob.com
  • 41.
    Be Careful w/DOM Only change the DOM state if it’s absolutely necessary - Avoid aggressive “synchronization” common in some AJAX toolkits (ex: our form sync example) Merge data together rather than replace - Partial page loads (div.innerHTML = ...) is also bad - Involves more work, but results in a much better experience when things don’t work well http://browsermob.com
  • 42.
    Lock the UI Don’tgive the user a chance to change things that might also get changed by you - In our form example: disable the form elements! - If necessary, use a modal dialog box to lock the entire UI But remember: have a recovery plan! - Test for failure and ensure that the UI unlocks when unexpected behavior occurs http://browsermob.com
  • 43.
    Inform the User Alwayskeep the user informed about what is happening Ideally give them an “escape hatch” if things go terrible wrong - Set thresholds for when to present the escape hatch - GMail is a good example of this At minimum, simple “loading” indicator http://browsermob.com
  • 44.
  • 45.
    Questions? Patrick Lightbody Founder, BrowserMob patrick@browsermob.com BrowserMob Proxy (Open Source) http://proxy.browsermob.com BrowserMob Services http://browsermob.com http://browsermob.com