Bug 1974469 Comment 0 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

Making Firefox as fast as Chrome on this function would reduce its time by 1.3% on TodoMVC-React-Redux

Profiles:
[Firefox](https://profiler.firefox.com/public/4mxk66ewtq36f9k7aahcf1mnvjt2q4mmh7k9820/flame-graph/?globalTrackOrder=0wx2&hiddenGlobalTracks=0wcewx2&profileName=Firefox%20Sp3NUC-20250604&symbolServer=http%3A%2F%2F127.0.0.1%3A3000%2F0kms4n4fl79kbxafq9jmisqn7r5n25qfy51gjv8&thread=d&transforms=fs-m--async%2C-sync~df-161~df-7576~df-7228~df-19438~df-1547~df-7230~df-2079~df-8940~fs-m-suite-TodoMVC-React-Redux~ff-9591~rec-9591~df-9593~df-4951~df-40605~df-15948~df-10380~df-5718~df-31256~df-5648~df-31333~df-31294~df-9909~df-10141~df-48062~df-9796~df-9968~df-9742&v=10)
[Chrome](https://profiler.firefox.com/public/zyp9djg3d5dnvt33gr5w8evdw03kamgne06dqn8/flame-graph/?globalTrackOrder=0wx4&hiddenGlobalTracks=0wbdwx4&profileName=Chrome%20Sp3NUC-20250604&symbolServer=http%3A%2F%2F127.0.0.1%3A3001%2F3s80cpkaxp2k6mx8mxj789daix21r8dyiq1z18j&thread=c&transforms=fs-m--async%2C-sync~df-818~df-12666~df-2687~df-1625~fs-m-suite-TodoMVC-React-Redux~ff-7778~rec-7778~df-2708~df-7780~df-12663~df-8050~df-9927~df-7944~df-13482~df-118664~df-34887~df-11652~df-34896~df-7946~df-7804~df-9638~df-10047~df-8049~df-70429~df-7786~df-17725~df-34923~df-7929~df-40012~df-52903~df-7910~df-22240&v=10)

Sample counts for the inner for loop:
SM: 1296
V8: 629

Some commentary from Iain:

A few observations, in the order that I bumped into them:

    We're testing if child is null and then unboxing it as an object, which is slightly redundant. V8 does a tiny bit better here.
    We're emitting spectre mitigations on our shape guards.
    childExpirationTime/expirationTime are in slots 21/22, which is larger than max fixed slots (16), so they're stored out-of-line. V8 stores them inline.
    V8 is doing enough field type tracking to know that child.expirationTime and child.childExpirationTime are Smis without needing to guard. We have fallible unboxes.
    V8 is keeping newChildExpirationTime in a register as an unboxed value. We're stored it boxed, and unboxing/reboxing it each time we update it.

Here's a microbenchmark that I think captures what's going on here: https://gist.github.com/iainireland/3a09e5ddc47d89cf23aa241b9ba8a079
I get around 165ms in the SM shell with spectre mitigations enabled, ~100ms with spectre disabled, and ~60-65ms in V8
Making Firefox as fast as Chrome on this function would reduce its time by 1.3% on TodoMVC-React-Redux

Profiles:
[Firefox](https://profiler.firefox.com/public/4mxk66ewtq36f9k7aahcf1mnvjt2q4mmh7k9820/flame-graph/?globalTrackOrder=0wx2&hiddenGlobalTracks=0wcewx2&profileName=Firefox%20Sp3NUC-20250604&symbolServer=http%3A%2F%2F127.0.0.1%3A3000%2F0kms4n4fl79kbxafq9jmisqn7r5n25qfy51gjv8&thread=d&transforms=fs-m--async%2C-sync~df-161~df-7576~df-7228~df-19438~df-1547~df-7230~df-2079~df-8940~fs-m-suite-TodoMVC-React-Redux~ff-9591~rec-9591~df-9593~df-4951~df-40605~df-15948~df-10380~df-5718~df-31256~df-5648~df-31333~df-31294~df-9909~df-10141~df-48062~df-9796~df-9968~df-9742&v=10)
[Chrome](https://profiler.firefox.com/public/zyp9djg3d5dnvt33gr5w8evdw03kamgne06dqn8/flame-graph/?globalTrackOrder=0wx4&hiddenGlobalTracks=0wbdwx4&profileName=Chrome%20Sp3NUC-20250604&symbolServer=http%3A%2F%2F127.0.0.1%3A3001%2F3s80cpkaxp2k6mx8mxj789daix21r8dyiq1z18j&thread=c&transforms=fs-m--async%2C-sync~df-818~df-12666~df-2687~df-1625~fs-m-suite-TodoMVC-React-Redux~ff-7778~rec-7778~df-2708~df-7780~df-12663~df-8050~df-9927~df-7944~df-13482~df-118664~df-34887~df-11652~df-34896~df-7946~df-7804~df-9638~df-10047~df-8049~df-70429~df-7786~df-17725~df-34923~df-7929~df-40012~df-52903~df-7910~df-22240&v=10)

Sample counts for the inner for loop:
SM: 1296
V8: 629

Some commentary from Iain:

A few observations, in the order that I bumped into them:

1. We're testing if child is null and then unboxing it as an object, which is slightly redundant. V8 does a tiny bit better here.
2. We're emitting spectre mitigations on our shape guards.
3. childExpirationTime/expirationTime are in slots 21/22, which is larger than max fixed slots (16), so they're stored out-of-line. V8 stores them inline.
4. V8 is doing enough field type tracking to know that child.expirationTime and child.childExpirationTime are Smis without needing to guard. We have fallible unboxes.
5. V8 is keeping newChildExpirationTime in a register as an unboxed value. We're stored it boxed, and unboxing/reboxing it each time we update it.

Here's a microbenchmark that I think captures what's going on here: https://gist.github.com/iainireland/3a09e5ddc47d89cf23aa241b9ba8a079
I get around 165ms in the SM shell with spectre mitigations enabled, ~100ms with spectre disabled, and ~60-65ms in V8

Back to Bug 1974469 Comment 0