Re: [css-fonts] Proposal for standardizing font timeout behavior

On Wed, Oct 29, 2014 at 9:23 PM, John Daggett <jdaggett@mozilla.com> wrote:
>
> Ilya Grigorik wrote:
> >> TPAC discussion led to some questions:
> >>
> >> 1. "optional" might be doable with Resource Hints instead - jdaggett
> >> wants us to investigate this.
> >
> > Unfortunately neither "optional" nor "swap" is possible with RH.
> >
> > The root problem is that there is no JS event or callback for "I'm
> > ready to paint this text block, tell me what to do" -- note that
> > "ready to paint text" has no relation to the state of the font
> > request, instead it simply indicates that the browser *could* paint
> > the text at this point in time. If we had such a callback, then we
> > could implement optional+swap with Font Events API, alas...
>
> As defined, the 'optional' keyword would always be effectively
> determined by whether a font had been loaded by a previous page,
> since layout initiates font loads and paint follows shortly after
> layout. So 'optional' in practice would be equivalent to "use the
> the font if it's already been cached".
>

The fact that a resource may be in a local cache does not mean it is
instantly available: you need to hit your spinning rust / flash, and you
(likely) need to hop between I/O and render threads. We have telemetry data
showing that even with flash, some disk accesses are in high double and
even triple digits of milliseconds, and on top of that you have thread
hops, which can also add non trivial amounts of overhead (although, often
less due to hops and instead due to contention between main thread being
busy and events accumulating in the queue).

Cache lookups are not free or instant, and from first hand experience in
Chrome, we can't count on font being available in time just because its
"cached"... There are cases where network fetches are faster than cache
lookups -- crazy, I know.


> The Font Loading API gives authors complete control over when fonts
> are loaded, precisely when they are used, and how the "swap" occurs.
>

Loads are not instant. Yes, we can kick off a .load() with Font Events API,
but that doesn't mean it'll complete in time for layout+paint.


> The "first paint" event you keep referring to is really "first
> layout", since font selection affects layout. If you feel the
> missing element is a "first layout" event for a given element, maybe
> that's what should be spec'ed instead.
>

In theory, paint should occur shortly after layout, but in practice there
are often big gaps (up to several hundred milliseconds), so I'm not sure we
want to necessarily tie these two concepts together. That said, if you give
me a "first layout event" for an element, then yeah, I could script the
behaviors we're talking about here. I'm not sure how realistic that is
though?

However, even with the JS event, defining this behavior would still require
quite a bit of JS work on behalf of developer. Personally, I'd still like
to see this as a CSS property. Text rendering (aka, communicating actual
information on the page) is the bread and butter of the web... It would
sure be nice to make delivering a performant text rendering experience
simple.

That said, I think trying to spec behavior on "first layout" is
> really tricky since the precise timing of this depends on the
> incremental layout algorithm used by a browser and that's going to
> vary across user agents/devices.
>

I don't think variability is the problem... I'd kick off my font request as
soon as possible, and then run a "is font ready" check in each element
layout callback to see if I can/should apply it or not.


> > That said, even if we did, it would still be a very involved
> > affair and fast text rendering is a big enough use case that, I
> > would argue, warrants a dedicated CSS API to make these behaviors
> > simple to implement and customize.
>
> Um, so instead we're proposing CSS properties that tweak fetch
> parameters?!? ;)
>

The behavior we're proposing here is not tweaking fetch parameters in any
way. To deliver the optimal experience you'd use this alongside Font Events
API to kick off an early fetch (from network or cache), and then use these
CSS properties to control behavior of text rendering at first layout+paint
of each element based on state of the font request.

- Font Events API allows me to start the font request sooner
- Browser is now racing font request and layout+paint work
- Browser gets to layout+paint and uses font-rendering to determine which
text rendering strategy it should apply
 -- if request has finished, it applies the font and moves on
 -- if request is still in flight, it applies specified strategy

> > 2. We need to define when the timeout starts counting.
> > >
> >
> > All performance timers are tied to startTime defined in
> NavigationTiming, I
> > think we should do the same:
> > http://w3c.github.io/navigation-timing/#startTime-attribute
> >
> > Effectively, time starts running the moment the navigation is triggered.
>
> This is not what any user agent implements currently. Font load
> timers start when layout decides it needs a given font.
>

As an alternative, we can tie to startTime of the font resource fetch:
http://www.w3.org/TR/resource-timing/#startTime-attribute

Above is closer to existing semantics, and it'll work for cases where font
request is initiated early - e.g. via font events api, RH hint, etc.


> >> 3. We probably need an "auto" value for letting the UA do what it
> >> wants, particularly as browsers seem to have behavior that is
> >> subtly more complex than what is being defined here.  For
> >> example, jdaggett said that Firefox's behavior is actually that
> >> when the initial 3s timeout expires, if the font has started
> >> downloading, it sets a second timeout that lets it go on a little
> >> longer.
> >
> > It would be really nice if we could explain default UA behaviors
> > via exposed primitives. If the current primitives are not
> > sufficient, then perhaps we should consider extending those
> > instead? Or, consider changing FF behavior to use defined
> > primitives? We need less magic in the platform.
>
> Ilya, you need to define what the default behavior is. If you don't
> want a single, standard behavior, then an 'auto' value is needed
> here, which would allow user agents to vary.
>

Personally, I'm ok with allowing UAs to customize own defaults. As Tab
noted:

FF and Chrome/Opera currently have a default of "mandatory 3s".  IE
> has a default of "mandatory 0s".  Safari has a default of "mandatory
> <infinite-time-value>".


If Safari team thinks "mandatory <infinite>" is the best user experience,
then let them use that. However, do allow me (the developer) to override
this strategy if that default is not suitable for my particular use case.

It's not clear to me why we need "auto" if above strategies already cover
implemented behaviors (modulo your second timer).

If you're going to talk about "primitives" then those primitives
> shouldn't be font-specific. The problem here is that you're trying
> to specify one small set of behaviors when the larger "how do user
> agents load and display resources quickly and efficiently?" is one
> big ball of magic.

I think the use of icon fonts would be a good use case example.
> How's does waiting on an icon font compare with waiting on a set of
> images? Whatever pattern is used for one should probably be similar
> to the other since all the reasons to control the layout of fonts
> applies just as equally to images, and vice versa. Sometimes images
> are progressive enhancement fluff, sometimes they are critical UI
> essentials, just like fonts.
>

These are fair points, but I do think that font rendering deserves special
attention. Rendering layouts with blank text is about as bad as it gets
(forget pretty layouts, we're omitting the actual key information on the
page) and hurts webfont adoption -- e.g. it's a roadblock for many latency
sensitive use cases and apps at Google (and beyond).

For images we have progressive rendering - e.g. developer can control how
image is rendered based on served format and encoding. Similarly, I think
each content-type may have own set of approaches for how to deal with this
problem. With fonts, we need to control this behavior on the client, hence
this proposal.

ig

Received on Thursday, 30 October 2014 05:33:57 UTC