Quantum Flow Engineering Newsletter #21

Ehsan Akhgari ehsan.akhgari at gmail.com
Fri Aug 25 06:57:32 UTC 2017

Hi everyone,

We're now about mid-way through the Firefox 57 development cycle.  The
of Quantum Flow bugs has been steady, we now have 65 open [qf:p1] bugs at
the time of this writing and 283 fixed bugs.  There are still more bugs
being flagged for triage constantly.  I haven't really spoken much about
the triage process lately and the reason is that it has been working as per
usual and the output should be fairly visible to everyone through our
dashboard <https://charts.mozilla.org/quantum/blockers.html>.

On the Speedometer front, if you are watching the main tracking
<https://bugzilla.mozilla.org/show_bug.cgi?id=1339557> bugs
<https://bugzilla.mozilla.org/show_bug.cgi?id=1245279>, the addition of new
dependencies every once in a while should be an indication that we are
still profiling the benchmark looking for more areas where we can think of
speedup opportunities.  Finding these new opportunities has become more and
more difficult as we have been fixing more and more of the existing
performance issues, which is exactly what you would expect working on
improving the performance of Firefox on such a benchmark workload.  Of
course, we still have ongoing work in the existing dependency tree (which
is quite massive at this point) so more improvements should hopefully
arrive as we keep landing more fixes on this front.

I realize that I have been quite inconsistent in having a performance story
section in these newsletters, and I hope the readers will forgive me for
that!  :-)  But these past couple of weeks, Jan de Mooij's continued effort
on removing getProperty/setProperty JSClass hooks
<https://bugzilla.mozilla.org/show_bug.cgi?id=1389510> from SpiderMonkey
made me want to write a few sentences about some useful lessons we have
learned from performance measurements which can hopefully be used in the
future when designing new components/subsystems.  Often times when we are
thinking of how to design software, one can think of many extension points
at various levels which consumers of the code can plug into in order to
customize behavior.  But many such extension points come at a *runtime cost*.
The cost is usually quite small, we may need to consume some additional
memory to store more state, we may need to branch on some conditions, we
may need to perform some more indirect/virtual calls, etc.  The problem is
that usually this cost is extremely small, and it can easily go unnoticed.
But this can often happen in many places, and over time performance issues
like this tend to creep in and hide in corners.  Of course, usually when
these extension points are added there are good reasons for creating them,
but it may be a good idea to ask questions like "Is this mechanism too high
level of a solution for this specific problem?", "Is the runtime cost paid
for this over the years to come justified to solve the issue at hand?",
"Could this issue be solved by adding an extension point in a more
specialized place where the added cost would only affect a subset of the
consumers?", etc.  The reality of software engineering is that in a lot of
cases we need to trade off having a generic, extensible architecture in our
code versus having efficient code, so if you end up choosing extensibility,
it's a good idea to ensure you have had the performance aspects in mind.
It's even better if you document the performance concerns!

And since we touched on this, now may be a good time to also take a quick
moment to call out another issue which I have seen come up on some of the
performance issues we have been looking into in the past few months.  That
is the *death by a thousand cuts performance problems*.  In my experience,
many of the performance issues that we need to deal with, when profiled
turn out to be caused by only a few really badly performing parts of the
code, or at least are due to a few underlying causes.  But we also have no
shortage of the other kind of performance issues which are honestly much
more difficult to deal with.  The way things work out in the opposite
scenario is you look at a profile from the badly performing case, you
narrow down on the section of the profile which demonstrates the issue, and
no matter how hard you squint, there are no major issues to be fixed.
Rather, the profile shows *many* individual issues each contributing to a
tiny portion of the time spent during the workload.  These performance
issues are much harder to analyze (since there are typically many ways you
can start approaching it and it's unclear where is a good place to start)
and they take a much longer time to result in measurable improvements, as
you'd need to fix quite a few issues in order to be able to measure the
resulting improvement.  For a good example of this, please look at the saga
of optimizing setting the value property of input elements
<https://bugzilla.mozilla.org/show_bug.cgi?id=1346723>.  This project has
been going on for a few months now, and during this time the workload has
been made faster by more than an order of magnitude, but still if you look
at each of the individual patches that have landed, they look like
micro-optimizations, and that's for a good reason, because they *are*.  But
overall they add up to significant improvements.

Before closing, it is worth mentioning that the ongoing performance work
isn't suddenly going to stop with the release of Firefox 57!  In fact we
have large performance projects which are going to get ready after Firefox
57, and that is a good thing, since I view Firefox 57 not as an ultimate
performance goal, but as a solid performance foundation for us to start
building upon.  A great example is the Quantum Render
<https://wiki.mozilla.org/Platform/GFX/Quantum_Render> project which has
been going on for a long time now.  This project aims to integrate the
WebRender <https://github.com/servo/webrender> component of Servo
<https://servo.org/> into Firefox.  This project now has an exciting
newsletter <https://mozillagfx.wordpress.com/category/wr-newsletter/>, and
the first two issues are out!  Please take a moment to check it out.

And now it is time to take a moment to thank the contributions of those who
helped make Firefox faster last week.  As usual I hope I'm not forgetting
any names!

   - Evelyn Hung made it so that when we tell the content process to load a
   URI, we first initiate a speculative connection in the parent process
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1383299> so that we don’t
   have to wait for the content process to request network access for the
   connection to be set up.  In a similar vein, Evelyn also made us initiate
   a speculative connection upon the mousedown event on an awesomebar result
   entry <https://bugzilla.mozilla.org/show_bug.cgi?id=1355451> to start
   setting up the network connection even faster when using the mouse to pick
   an awesomebar result.
   - Paolo Amadini made FileUtils.getFile() not do main-thread IO for the
   common case <https://bugzilla.mozilla.org/show_bug.cgi?id=1391576>.  You
   may remember some fixes to callers of this function were mentioned in the
   previous newsletters to avoid this pattern of main-thread IO, and this fix
   will hopefully address this issue for most of the remaining callers. Paolo
   also got rid of some reflows
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1358792> we were doing
   when opening up the AwesomeBar panel.
   - prasanthp96 deferred reading several preferences
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1383088> to reduce their
   impact on startup performance.
   - Botond Ballo enabled support for asynchronous autoscrolling on the
   Nightly channel <https://bugzilla.mozilla.org/show_bug.cgi?id=1390247>.
   - André Bargull inlined IsCallable when called from MIRType::Value
   - Olli Pettay added a nursory to the cycle collector purple buffer
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1391423> in order to speed
   up AddRef/Release calls to cycle collectible objects on the main thread.
   He also added a faster variant of TextEditor::GetDocumentIsEmpty()
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1390402> in order to speed
   up setting the value property of input elements.
   - Ming-Chou Shih enabled coalescing mousemove events to once per refresh
   cycle <https://bugzilla.mozilla.org/show_bug.cgi?id=1361067>.  This
   feature helps performance by dispatching fewer mousemove events on pages
   which have expensive mousemove handlers, and is shipped in Chrome
   <https://www.chromestatus.com/feature/6192761317359616> recently.  It is
   currently disabled <https://bugzilla.mozilla.org/show_bug.cgi?id=1392876>
   behind a preference for testing.
   - Kris Maglione cached some extension manifest data in the startup cache
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1389840>.  He also converted
   FrameLoader bindings to WebIDL
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1391110> for improved
   performance of the JS code going through these bindings to access the
   underlying C++ code.  He also made the WebExtension schema normalization
   code faster <https://bugzilla.mozilla.org/show_bug.cgi?id=1391405>.
   Last but not least, Kris added a UI for notifying the user about long
   running WebExtension content scripts and provide the option to stop them
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1356334>, similar to the
   existing UI we have for long running content scripts.  While this isn't
   strictly a performance improvement in itself, it is worthy of mention here
   because it allows the user to interrupt a badly behaving WebExtension
   content script causing performance issues.
   - Masayuki Nakano optimized
   - Jessica Jong made sure we skip the potentially expensive pattern
   matching code when validating input elements if the element has no pattern
   attribute set <https://bugzilla.mozilla.org/show_bug.cgi?id=1390342>.
   - Jan de Mooij devirtualized MNode::kind()
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1391611> and
   MDefinition::op() <https://bugzilla.mozilla.org/show_bug.cgi?id=1392530>.
   - Bao Quan moved _saveStateAsync to the idle event queue
   - John Dai ensured that we avoid processing custom element reactions
   stack when web components are disabled
   - Makoto Kato enabled lazy frame construction in editable regions of
   HTML documents <https://bugzilla.mozilla.org/show_bug.cgi?id=1348073>.
   The original lazy frame construction optimization
   <https://bugzilla.mozilla.org/show_bug.cgi?id=502937> was enabled in
   2010 and shipped in Firefox 4 but it never covered editable sections of
   HTML documents such as contents of input and textarea textboxes as well as
   contenteditable elements until now.
   - Doug Thayer made it so that we avoid some main thread IO
   <https://bugzilla.mozilla.org/show_bug.cgi?id=1389443> when registering
   MIME-type handlers on start-up.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/firefox-dev/attachments/20170825/62f980ef/attachment-0001.html>

More information about the firefox-dev mailing list