Infrequently Noted

Alex Russell on browsers, standards, and the process of progress.

Towards a Unified Theory of Web Performance

Note: This post first ran as part of Sergey Chernyshev and Stoyan Stefanov's indispensible annual series. It's being reposted here for completeness, but if you care about web performance, make sure to check out the whole series and get subscribed to their RSS feed to avoid missing any of next year's posts.

In a recent Perf Planet Advent Calendar post, Tanner Hodges asked for what many folks who work in the space would like for the holidays: a unified theory of web performance.

I propose four key ingredients:

  • Definition: What is "performance" beyond page speed? What, in particular, is "web performance"?
  • Purpose: What is web performance trying to accomplish as a discipline? What are its goals?
  • Principles: What fundamental truths are guiding the discipline and moving it forward?
  • Practice: What does it look like to work on web performance? How do we do it?

This is a tall order!

A baseline theory, doctrine, and practicum represent months of work. While I don't have that sort of space and time at the moment, the web performance community continues to produce incredible training materials, and I trust we'll be able to connect theory to pracice once we roughly agree on what web performance is and what it's for.

This Is for Everyone

Missing alt text
Tim Berners-Lee tweets that 'This is for everyone' at the 2012 Olympic Games opening ceremony using the NeXT computer he used to build the first browser and web server.
Tim Berners-Lee tweets that 'This is for everyone' at the 2012 Olympic Games opening ceremony using the NeXT computer he used to build the first browser and web server.

Embedded in the term "web performance" is the web, and the web is for humans.

That assertion might start an argument in the wrong crowd, but 30+ years into our journey, attempts to promote a different first-order constituency are considered failures, as the Core Platform Loop predicts. The web ecosystem grows or contracts with its ability to reach people and meet their needs with high safely and low friction.

Taking "this is for everyone" seriously, aspirational goals for web performance emerge. To the marginal user, performance is the difference between access and exclusion.

The mission of web performance is to expand access to information and services.

Page Load Isn't Special

It may seem that web performance comprises two disciplines:

  1. Optimising page load
  2. Optimising post-load interactions

The tools of performance investigators in each discipline overlap to some degree but generally feel like separate concerns. The metrics that we report against implicitly cleave these into different "camps", leaving us thinking about pre- and post-load as distinct universes.

But what if they aren't?

Consider the humble webmail client.

Here are two renderings of the same Gmail inbox in different architectural styles: one based on Ajax, and the other on "basic" HTML:

The Ajax version of Gmail with two messages
The Ajax version of Gmail loads 4.8MiB of resources, including 3.8MiB of JavaScript to load an inbox containing two messages.

The same inbox in Gmail's 'simple HTML' mode
The 'basic' HTML version of Gmail loads in 23KiB, including 1.3KiB of JavaScript.

The difference in weight between the two architectures is interesting, but what we should focus on is the per interaction loop. Typing in the address bar, hitting Enter, and becoming ready to handle the next input is effectively the same interaction in both versions. One of these is better, and it isn't the experience of the "modern" style.

These steps inform a general description of the interaction loop:

  1. The system is ready to receive input.
  2. Input is received and processed.
  3. Progress indicators are displayed.
  4. Work starts; progress indicators update.
  5. Work completes; output is displayed.
  6. The system is ready to receive input.

Tradeoffs In Depth

Consider the next step of our journey, opening the first message. The Ajax version leaves most of the UI in place, whereas the HTML version performs a full page reload. Regardless of architecture, Gmail needs to send an HTTP request to the server and update some HTML when the server replies. The chief effect of the architectural difference is to shift the distribution of latency within the loop.

Some folks frame performance as a competition between Team Local (steps 2 & 3) and Team Server (steps 1 & 4). Today's web architecture debates (e.g. SPA vs. MPA) embody this tension.

Team Local values heap state because updating a few kilobytes of state in memory can, in theory, involve less work to return to interactivity (step 5) while improving the experience of steps 2 and 3.

Intuitively, modifying a DOM subtree should generate less CPU load and need less network traffic than tearing down the entire contents of a document, asking the server to compose a new one, and then parsing/rendering it along with all of its subresources. Successive HTML documents tend to be highly repetitive, after all, with headers, footers, and shared elements continually re-created from source when navigating between pages.

But is this intuitive understanding correct? And what about the other benefits of avoiding full page refreshes, like the ability to animate smoothly between states?

Herein lies our collective anxiety about front-end architectures: traversing networks is always fraught, and so we want to avoid it being jarring. However, the costs to deliver client-side logic that can cushion the experience from the network latency remain stubbornly high. Improving latency for one scenario often degrades it for another. Despite partisan protests, there are no silver bullets; only complex tradeoffs that must be grounded in real-world contexts — in other words, engineering.

As a community, we aren't very good at naming or talking about the distributional effects of these impacts. Performance engineers have a fluency in histograms and percentiles that the broader engineering community could benefit from as a lens for thinking about the impacts of design choices.

Given the last decade of growth in JavaScript payloads, it's worth resetting our foundational understanding of these relative costs. Here, for instance, are the network costs of transitioning from the inbox view of Gmail to a message:

Missing alt text
Displaying the first message requires 82KiB of network traffic in the Ajax version of Gmail, half of which are images embedded in the message.
Displaying the first message requires 82KiB of network traffic in the Ajax version of Gmail, half of which are images embedded in the message.

Displaying a message in the 'basic' HTML version requires a full page refresh.
Displaying a message in the 'basic' HTML version requires a full page refresh.

Despite fully reloading the page, the HTML version of Gmail consumes fewer network resources (~70KiB) and takes less overall time to return to interaction.
Despite fully reloading the page, the HTML version of Gmail consumes fewer network resources (~70KiB) and takes less overall time to return to interaction.

Objections to the comparison are legion.

First, not all interactions within an email client modify such a large portion of the document. Some UI actions may be lighter in the Ajax version, especially if they operate exclusively in the client-side state. Second, while avoiding a full-page refresh, steps 2, 3, and 4 in our interaction loop can be communicated with greater confidence and in a less jarring way. Lastly, by avoiding an entire back-and-forth with the server for all UI states, it's possible to add complex features — like chat and keyboard accelerators — in a way that doesn't incur loss of context or focus.

The deeper an app's session length and the larger the number of "fiddly" interactions a user may perform, the more attractive a large up-front bundle can be to hide future latency.

This insight gives rise to a second foundational goal for web performance:

We expand access by reducing latency and variance across all interactions in a user's session to more reliably return the system to an interactive state.

For sites with low interaction depths and short sessions, this implies that web performance engineering might remove as much JavaScript and client-side logic as possible. For other, richer apps, performance engineers might add precisely this sort of payload to reduce session-depth-amortised latency and variance. The tradeoff is contextual and informed by data and business goals.

No silver bullets, only engineering.

Medians Don't Matter

Not all improvements are equal. To understand impacts, we must learn to think in terms of distributions.

Our goal is to minimise latency and variance in the interactivity loop... but for whom? Going back to our first principle, we understand that performance is the predicate to access. This points us in the right direction. Performance engineers across the computing industry have learned the hard way that the sneaky, customer-impactful latency is waaaaay out in the tail of our distributions. Many teams have reported making performance better at the tail only to see their numbers get worse upon shipping improvements. Why? Fewer bouncing users. That is, more users who get far enough into the experience for the system to boot up in order to report that things are slow (previously, those users wouldn't even get that far).

Tail latency is paramount. Doing better for users at the median might not have a big impact on users one or two sigmas out, whereas improving latency and variance for users at the 75th percentile ("P75") and higher tend to make things better for everyone.

As web performance engineers, we work to improve the tail of the distribution (P75+) because that is how we make systems accessible, reliable, and equitable.

A Unified Theory

And so we have the three parts of a uniform mission, or theory, of web performance:

Perhaps a better writer can find a pithier way to encapsulate these values.

However they're formulated, these principles are the north star of my performance consulting. They explain tensions in architecture and performance tradeoffs. They also focus teams more productively on marginal users, which helps to direct investigations and remediation work. When we focus on getting back to interactive for the least enfranchised, the rest tends to work itself out.

Minimum Standards for iOS Browser Competition

There has been a recent flurry of regulatory, legislative, and courtroom activity regarding mobile OSes and their app stores. One emergent theme is Apple's shocking disregard for the spirit of legal findings it views as adverse to its interests.

Take, for instance, Apple's insistence that it would take "months" to support the addition of links to external payment providers from within apps, nevermind it had months of notice. There is a case to be made that formulating policy and constructing a comissions system takes time, but this is ridiculous.

Just sit with Apple's claim a moment. Cupertino is saying that it will take additional months to allow other people to add links within their own apps.

Or consider South Korea's law, passed last August, that elicited months of stonewalling by Google and Apple until, at last, an exasperated KCC started speaking a language Cupertino understands: fines. Having run the clock for half a year, Apple has started making noises that indicate a willingness to potentially allow alternative payment systems at some point in the future.

Never fear, though; there's no chance that grudging "compliance" will abide the plain-language meaning of the law. Apple is fully committed to predatory delay and sneering, legalistic, inch-measuring conformance. Notably, it signaled it feels entitled to skim equivalent revenues to it's monopoly rents for payments paid through third-party processors in both Korea and the Netherlands. If regulators are going to bring this to heel, they will need to start assuming bad-faith.

Dutch regulators have been engaged in a narrowly-focused enquiry into the billing practices of dating apps, and they came to remarkably similar conclusions: Apple's pracctices are flagarantly anti-competitive.

In a malign sort of consistency, Apple responded in the most obtuse, geographically constrained, and difficult-to-use solution possible. Developers would need to submit a separate, country-specific version of their app, only available from the Dutch version of the App Store, and present users with pejorative messaging. Heaven help users attempting to navigate such a mess.

This "solution" was poorly received. Perhaps learning from the KCC's experience, Dutch regulators moved to impose fines more quickly, but perhaps misjudged how little 50 million EUR is to a firm that makes 600× as much in profit per quarter. It certainly hasn't modulated Apple's duplicitous audacity.

Cupertino's latest proposed alternative to its 30% revenue cut will charge developers that use external payment processors a 27% fee which, after the usual 3% credit card processing fee... well, you can do the math.

Regulators in the low countries are rightly incensed, but Apple's disrespect for the rule of law isn't going to be reformed by slowly deployed half-measures, one vertical at a time. Structural change is necessary, and the web could bring that change if it is unshackled from Apple's slipshod browser engine.

A Floor for Functional Browser Choice

With all of this as context, we should seriously consider how companies this shameless will behave if required to facilitate genuine browser choice. What are the policy and technical requirements regulators should set to ensure fairness? How can the lines be drawn so delay and obfuscation aren't used to scuttle capable competitors? How can regulators anticipate and get ahead of brazenly bad-faith actions, not only by Apple, but Google and Facebook as well?

Geographic Games

One oligopolist response has been to change anti-competitive behaviour only within small markets, e.g. making changes only to the "dating" category of apps and only within the Netherlands. Apple and Google calculate that they can avoid the Brussels Effect by making a patchwork set of market-specific changes. A goal of this strategy is to confuse users and make life hard for rebellious developers by tightly drawing "fixes" around the letter of the law in each jurisdiction.

While technically meeting legal requirements, these systems will be so hard to use that residents and businesses blame regulators, rather than store proprietors for additional day-to-day inconvenience. Because they're implemented in software, this market well-poisoning is cost-free for Apple. It also buys bad-faith actors months of delay on substantive change while they negotiate with regulators.

Could regulators include language that stipulates how market fairness requirements cannot be met with country-specific versions of apps or capabilities? This quickly hits jurisdictional boundaries, likely triggering years of court appeals. This is undesirable as delay is the ne'er do well's friend.

Regulators generally have scope over commerce within their territorial borders. Multilateral treaty organisations like the the WTO have supranational jurisdiction but no appetite or the treaty scope to tackle firm-level competition issues. They focus instead on tariffs and "dumping" practices that privilege one nation's industries over another, as those are the sorts of disputes national laws cannot address.

A More Durable Approach

Effective regulation needs market-opening technologies that function without constant oversight. The lines drawn around undermining this technology should be so clear, and the consequences for stepping over them so painful, that even Apple, Google, and Facebook dare not go near them.

When regulators adopt similar (if not identical) regulations they increase the costs to bad actors of country-specific gamesmanship. Regulators that "harmonise" their interventions multiply the chances of compliance, creating a "Brussels of the Willing".

A competitive landscape for web browsers should be part of any compliance framework because:

For the web to perform these essential market functions on mobile, regulation must disrupt the status quo and facilitate competition from within. This also provides a solution to user safety and security concerns that pervasive sideloading may raise, as browsers are aggressively sandboxed. Meanginful choice, coupled with powerful browsers, can deliver better outcomes:

Table Stakes

Discussion of sideloading and alternative app stores often elides requirements that regulators should put in place to create competition amongst capable browsers. I have previously proposed a set of minimal interventions to ensure meaningful user choice. To restate the broadest points:

iOS Specifics

Because Apple's iOS is egregiously closed to genuine browser competition, regulators should pay specific attention to the capabilities that vendors that port engines will need. They should also ensure other capabilities are made available by default; the presumption for browser developers must be open access. Apple has shown itself to be a serial bad-faith actor regarding competition and browser choice, so while an enumeration of these features may seem pedantic, it sadly also seems necessary.

Today, Apple's Safari browser enjoys privileged access to certain APIs necessary for any competing browser vendor that wants to match Safari's features. Only Safari can:

As a general rule, competing browsers must also be allowed access to all private and undocumented APIs that are used by Safari, as well as iOS entitlements granted to other applications.

Regulators must also ensure capabilities are not prohibited or removed from browsers by secret agreements that Cupertino forces developers to sign. Further (and it's a shame this has to be said), Apple must not be allowed to comply with these terms by further neutering Safari's already industry-trailing feature set.

Apple must also be required to allow browsers with alternative engines to be procured directly through its App Store. It is easy to predict a world of country-specific sideloading regulations, with Apple attempting to blunt the impact of competitive browsers by continuing to banish them from their "legit" discovery surface.

Web browsers must also be allowed to implement the Web Payments API without being forced to use Apple Pay as the only back end. Apple must further be enjoined from requiring specific UI treatments that subvert these flows and prejudice users away from open payment systems.

Lastly, Apple must not be allowed to publish new versions of browsers through an arbitrary and capricious "review" process. Regulators must demand that Apple be forced to publish new browser versions and, if it objects to features within them, file a request for regulatory arbitration of the dispute post publication. Apple has long demonstrated it cannot be trusted with the benefit of the doubt in this area, and allowing updates to flow quickly is critical to ensuring users of the web remain safe.

Only within the contours of this sort of regime can ongoing enforcement of negotiated policy proceed in good faith.

Older Posts

Newer Posts