Giter Site home page Giter Site logo

audits's People

Contributors

paulirish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

audits's Issues

Adobe Edge JS: code pitfall? Never ending calls to requestAnimationFrame resulting in power inefficient ads.

While doing a deep dive on crbug.com/668810 "Message board burns an insane amount of energy", I found what seems to be an oversight in Adobe Edge JS.

Adobe Edge JS is/was(?) a popular framework used for animated ads and the issue was observed in this particular ad. However, I believe that this would be a common issue for any animated ad that uses Adobe Edge.

DevTools timeline
The screenshot below shows the activity of an ad using Adobe Edge well after it reached its last frame and became visually static:

pasted1

You can see that there is a fair amount of activity which correspond to requestAnimationFrame callbacks.
I step-debug the code and found that the framework does check for when an animation reaches its intended duration to notify "observers" but it fails to terminate the animation loop.

In particular, here is the code that drives the animation loop

 k.timerFunc = function() {
    c.Timeline.tick();
    k.requestAnimationFrame.call(window, k.timerFunc)
 };

 a.tick = function() {
        var a = b.slice(0);
        b = [];
        for (var c = a.length, d = (new Date).getTime(), g = 0; g < c; g++) {
            var n = a[g];
            typeof n !== "undefined" && n.call(null, d)
        }
 };

The b variable appears to represent the animation timeline.
When the ads run its course, b is empty but the timerFunc function itself doesn't check for this end state and as far as I could tell there was nothing in the code that would put an end to the timerFunc animation loop.

code.nasa.gov (pre-rewrite) audit

Speeding up the NASA OSS frontend before we rewrote it

Audit from: September

In this audit, we're going to explore and speed-up up the front-end to the NASA open-source projects landing page. We noticed code.nasa.gov was particularly slow on desktop over cable and heavy enough to lock up Chrome on Android on a relatively fast Wifi connection. We observed lots of main-thread lockup with very large chunks of work (some of the heaviest frames taking 2500ms+ when we really want this closer to 16ms):

screenshot from 2016-09-07 16 20 43

and the Network waterfall indicated there were 433 requests in flight. That's one busy request party.

screenshot from 2016-09-07 16 22 58

There are four primary causes of slow-down in this app:

  • Lots of Angular 1 code where switching to onetime bindings and avoiding XHRs for partials would help
  • Heavy use of embeds loading third-party content (Github buttons) for every OSS project entry on the page (290+)
  • Lots of syncronous font loading (5+ fonts being pulled in from Google Fonts)
  • Heavy image assets

Audit

Let's begin with some low hanging fruit. We noticed the site had a few larger image assets. This was trivial to fix and a pass through ImageOptim saved us 20-80% (333KB overall) on our page weight:
nasa/code-nasa-gov@974b08f

Next up we noticed each repo entry on their landing page had a GitHub fork button embed on it:

screenshot from 2016-09-07 16 27 36

Each GitHub button embed loaded via an iframe introduces additional network overhead of a few seconds (2.6/2.9s in a few cases on cable).

screen shot 2016-09-03 at 9 50 09 am

Overall these are responsible for over 1500ms+ of activity on the main thread (including time for JS execution) that isn't really offering us that much value:

screenshot from 2016-09-07 16 40 22

This PR I landed dropping them in favor of folks clicking through to the repo link at the top of each listing instead: nasa/code-nasa-gov@fc44bee

screen shot 2016-09-03 at 9 48 08 am

The impact of this change is we also get to remove 92 additional requests from the current network waterfall:

screen shot 2016-09-03 at 9 51 30 am

which is but also nixes 100KB+ from the overall payload.

We head back into the network panel and what do we see. Well, images again. We've optimised them all but there's still this
really large background image that ideally would be <100KB:

screenshot from 2016-09-07 16 32 27

Let's fix that by running it through https://compressor.io/ and we'll save 75% on the size of that asset: nasa/code-nasa-gov@ba96415

Looking through the network panel again we've got lots of web fonts. Whaa:

screenshot from 2016-09-07 16 44 37

We don't want to mess with the design of this page just yet but it definitely has too many fonts on there. Let's at least make sure we async load them in. If we switched to a Web Font Loader (like this) and used it asynchronously we would avoid blocking the page while loading in Angular and Bootstrap.

<link href='//fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Source+Code+Pro' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Exo+2:400,600,700' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Special+Elite' rel='stylesheet' type='text/css'>

nasa/code-nasa-gov@a388033

Downside to this is if we use it asynchronously, the rest of the page might render before the Web Font Loader is loaded and executed, which might intro some FOUC. But for now, we're going to land it.

Next, let's dig in and see what can be done about the Angular 1 perf issues on the app. If we CPU profile it in DevTools we see that $digest cycles are taking over 2 seconds!.

screenshot from 2016-09-07 17 28 29

If we wanted to get framework specific here, we could use ng-idle-apply-timing, which tries to run the digest cycle without changing any data and collects the CPU profile. It measures how long dirty checking for each piece of data in our app takes (two-way data-binding, $watch expressions..things that add to the digest cycle time). Looking at this we see that one idle digest cycle takes up a second. Not great.

screenshot from 2016-09-07 17 29 55

We can also get some insight into how many watch expressions Angular is evaluating by running ng-count-watchers, which goes through each element's scope, summing the total number of found watchers. In our case it's over 10,000:

screenshot from 2016-09-07 17 37 35

This is unnecessary overhead as all of our Github repo entries are being loaded in from a static JSON file (the source for data in this app) and aren't going to change.

screenshot from 2016-09-07 17 43 22

We can greatly simplify this by switching from two-way to one-way bindings in our code instead. Sam did this over here: nasa/code-nasa-gov@8b2d7e7 and also bumped us up to the latest version of Angular so the page would benefit from any performance improvements that landed since the page was created.

       <div ng-repeat="project in filtered = (catalog | orderBy:'Update_Date':true | filter:search)" class="box" ng-show="project.tagFilter">
          <div class="title">
            <div class="title1">
            <h2>{{:: project.Software}}</h2>
            </div>

Our improvements up until this point have been deployed to code.nasa.gov on Thursday 8th Sept. We're going to keep hacking on perf after this.

Update September 16th

The current version of the front-end didn't have a build step and there were places where it still used JavaScript to fetch a lot of partials, like the templates for entries, sharing and the license (taking 2s to fetch and 630ms+ to parse/execute on a fast Linux desktop):

screenshot from 2016-09-07 16 51 41

The site also doesn't currently concat any of the scripts or stylesheets, contributing to that high network request count. Introducing a simple build step here would allow us to start cutting away at some more low-hanging fruit. I landed a PR that added the following to try ameliorating the issue:

  • Angular template caching for partials (no more XHRs required for any templates)
  • Move scripts from <head> and switch to asynchronously loading them in
  • Gulp build process (can ES2015 later) for script concatenation and minification
  • Vendor scripts (Angular, Bootstrap etc) are localised to enable concatenation

This takes the work that was required here:

partials

and reduces it to:

partials-after

saving on a few hundred milliseconds on the aggregate time for these two blocks of work:
partials-1

To be clear, there's still a lot of work being done here. The change is we've switched to a single 319KB bundle for all script rather than 7 network requests for scripts and up to 11 additional requests for HTML partials.

Room for improvement:
We could get more granular here. We could only use template caching for partials needed for the initial view and continue XHRing in partials for Guide and Share.

Update November 11th

After reviewing the bottlenecks getting Angular 1 fast enough on mobile devices, we decided to completely rewrite the front-end using the PRPL pattern with Polymer (it made doing the rewrite using code-splitting techniques super easy and enabled us to ship in under a week). We'll be sharing more details on the implementation in the near future.

[m.imgur.com] page load performance

🏇 m.imgur.com page load perf 🏇


**TL;**DR

While server-side rendering is critical to get a fast first meaningful paint on
single page apps, JS can still undermine the user experience advantages of
server-side rendering.

By disabling javascript on m.imgur.com, the time from navigation→ the paint of
the primary image is decreased by more than 50% from around 7 seconds to 3
seconds (on a nexus 5 - 3g connection).


What:

m.imgur.com recently rolled out a new version of the site moving from a backbone
app to a serverside rendered React app.

Per usual I was looking at the latest Nicolas Cage gifs when I noticed that the
page seemed to feel sluggish when first loaded, preventing me from being able to
scroll down to see the comments or even see the complete image for almost 2
seconds. Now I don't know about you but 2 seconds between me and Cage is simply
unacceptable.


Looking at a timeline recording of loading an
image on imgur on my phone (Nexus 5) the problem is made quite clear.

image

Because the page is rendered serverside, the image starts to download right away, and gets progressively rendered and displayed to the user. However, the image appears to stop loading at around 3 seconds, which directly lines up with when a whole bunch of JavaScript starts to execute.

image

The fun thing about all of this JavaScript executing is that it is locking up
the main thread in the browser, thus preventing the image from being painted to
the screen until the JS work is all done. As an experiment I loaded the page
with JavaScript disabled just to see the performance difference and was not
surprised to see the page take well under ½ as long to finish displaying the
complete image with 0 user facing jank.

The Why:

When we look at the first long frame and sort the javascript activity by bottom
up we see that the browser is spending almost 40% of the time in two methods
called o and then two anonymous functions…
image

Looking close at the logic in those methods we see a familiar face:

image

It is the browserify module loading logic, this is the exact same problem that we ran into on
tumblr.com.

The next most relevant bit of logic is all contained in the React mount logic;
there may be some slight optimizations to be had here, but it is far away from
being the biggest offender.

image

The "Fix":

The interesting story around imgur is how by moving to a server side rendered
site, you would think that the performance gains would be immense. However, the
time spent in the javascript bootup phase is causing a negative user experience,
due to the JS execution blocking the main thread, and thus blocking image
rendering. This problem, while almost undetectable on a macbook pro or modern
computer, is painfully obvious when you test the site on a mobile phone on a
non-wifi internet connection. There are several ways to fix this issue, all of
which do not require an overwhelming amount of work.

  1. Defer the JavaScript execution until the image onload event
  2. Use a tool like rollup or Nolan Lawson's new rollupify
    https://github.com/nolanlawson/rollupify/
    to drop the overhead (40% of the JS time) of browserify
  3. Break up any block of script that takes over 100ms. Potentially use a
    scheduling API like
    requestIdleCallback.
    https://twitter.com/igrigorik/status/706890158323269633

Reddit back button responsiveness

This is a request for an audit of a strange issue I have been encountering lately. With the new mobile website (m.reddit.com) when I open a post and within a second hit my backbutton on my Android phone, there is a delay of a couple of seconds. It looks to me that the comment loading is causing a bottleneck before the backbutton is triggered, but I am not sure. Interested to hear about your findings or if you encountered this issue at all.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.