Amphtml: Slow Rendering for amp-list when binding="always" enabled

Created on 16 May 2019  路  12Comments  路  Source: ampproject/amphtml

What's the issue?

There is a significant delay when an amp-list has binding="always" enabled. The delay is exaggerated on production pages when more amp-components and other elements are present on the page.

Screen Shot 2019-05-16 at 11 54 18 AM

Screen Shot 2019-05-16 at 11 54 30 AM

Video of Delay
https://screencast-o-matic.com/watch/cqhDqzTecy

How do we reproduce the issue?

https://wompmobileamp.azureedge.net/7605/ampBindListSlow.html

  1. Visit the page above in Chrome Mobile Emulator with these settings
    a. 9Mbps network speed
    b. 4x CPU reduction

What browsers are affected?

Chrome on slower Android devices
Chrome Mobile Emulator with 4x CPU reduction

Which AMP version is affected?

Current version

Bug runtime

Most helpful comment

Found the cause and working on a fix. Sorry didn't recognize there was a problem in your prior comment.

All 12 comments

@jerimiahwelch I believe this would largely be addressed when the "Performance" bullet points in #21901 are checked-off.

This issue causes a 2 second delay for any of our amp pages that use amp-list + amp-bind. We have provided a generic example, but this is impacting a very large number of ecommerce amp pages every day. Is there anything we can do in the amp-list (besides not use amp-bind) to reduce the rendering delay?

@jerimiahwelch Is it possible to use binding=refresh instead of binding=always? The latter is slow in part because it requires downloading both extensions (amp-list & amp-bind) on client and doing client-side rendering.

@choumx

A common use case for this is enabling a qty incrementor for a dynamically downloaded price, but there are many other reasons we run across where we need to use amp-bind in conjunction with amp-list.

The issue here is not waiting for amp-list and amp-bind to become available. The issue is that the framework appears to forget about rendering the amp-list. You can see in the waterfall below that amp-list and amp-bind are both available, the CPU settles down, but the framework waits doing nothing for a long time before rendering the list.

bindAndListAvailability

Thanks for clarifying.

I believe the reason for the large delay is amp-bind's initialization which defers to requestIdleCallback. This is because amp-bind was originally designed to not affect user-perceived page load performance, which is why using binding=always is a performance pitfall.

However, I think the following in #21901 will help significantly:

Don't block scanForBindings on amp-bind's DOM scan if possible

I'll try to take a crack at this soon.

Thank you.

Here is an example of when we need amp-list + amp-bind ( video works well when viewed in a small browser window)
https://screencast-o-matic.com/watch/cq1qFFTJqJ

The price at the top varies according to quantity and subscriptions status.

The locale-specific currency depends on a geo-ip and customer-cookie aware API (this AMP page is reused in a PWA on the host domain).

Currently this works great in amp, but there is an initial delay to show the price.

Note that you can still use amp-list + amp-bind together with binding=refresh, it just won't apply on page load -- this means you'd need to server-side render the initial price.

In practice, we have experienced amp-bind interactions never loading when using binding="refresh", so we have steered away from it.

I am also unclear from reading the documentation when the binding is supposed to be applied. Refresh of the amp-list or some other time?

It works the same as binding=always except for the first render (page load). Its intended usage is exactly for amp-list + amp-bind interactions while avoiding the initial load performance problem.

For example:

<template id=sharedTemplate type=amp-mustache>
  <p [text]="1+1">0</p>
</template>

<!-- Will always render "0". -->
<amp-list binding=no template=sharedTemplate></amp-list>

<!-- Will render "0" on page load, but render "2" when the button is tapped. -->
<amp-list binding=refresh template=sharedTemplate></amp-list>
<button on="tap:AMP.setState({})">setState</button>

<!-- Will render "2" on page load. -->
<amp-list binding=always template=sharedTemplate></amp-list>

Sorry about any confusion. The attribute naming and documentation can be improved.

<!-- Will render "0" on page load, but render "2" when the button is tapped. -->

@choumx This example does not appear to be consistent with your definition:

  1. Visit https://android.cmphys.com/temp/amp-list-binding-refresh-bind.html
  2. Switch to mobile emulation
  3. Scroll to end of page
  4. Refresh page (refreshed page should load scrolled to bottom)
  5. Scroll to top of page
  6. Click "Make text green"

In my testing, the reliability of text turning green within the first amp-list is inconsistent. After clicking "Refresh amp-lists" the text color changes apply fine. I commented on this in #22043. It was after creating this example that I changed my interpretation of what binding="refresh" is supposed to do from "applies bind changes after first load" to "applies bind changes after amp-list src is changed or refreshed". Is this actually a bug, though?

Huh, looks like a bug.

Found the cause and working on a fix. Sorry didn't recognize there was a problem in your prior comment.

Was this page helpful?
0 / 5 - 0 ratings