Closed Bug 1360526 Opened 7 years ago Closed 7 years ago

Parallelise more table sweeping

Categories

(Core :: JavaScript: GC, enhancement)

55 Branch
enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla55
Tracking Status
firefox55 --- fixed

People

(Reporter: jonco, Assigned: jonco)

Details

Attachments

(10 files)

When we start to sweep a group of zones there are several tables that need to be swept and this is done non-incrementally so as to be atomic from the point of view of the mutator.

Most but not all of this work is performed in parallel using the JS helper threads.  We should parallelise as much as possible of the remaining work.

(The long term goal here is to do this work incrementally, but it seems like this would be an easy win)
First of all, refactor part that queues arenas for sweeping to use a single loop to iterate the zones.
Attachment #8863774 - Flags: review?(sphink)
Create a new sweep task for sweeping weak maps in parallel.  The wrinkle here is that sweeping debuggers may update some debugger weak maps, so do this on the main thread before we do anything else.  Use of debuggers is rare so this is not a performance concern.
Attachment #8863776 - Flags: review?(sphink)
Attached patch 3 - sweep-miscSplinter Review
Move some miscellaneous sweeping into the 'sweep misc' task.  We don't need to sweep all watchpoints in a zone GC since the cross-compartment closure pointer they hold is traced strongly during marking.  We do need to trace all watchpoints during a compacting GC since other zones may have watchpoints with closures that are in compacting zones.
Attachment #8863778 - Flags: review?(sphink)
Sweep runtime-wide weak caches as part of the sweep weak caches task.  I factored the iteration of per-zone and per-runtime caches out into a separate function.
Attachment #8863779 - Flags: review?(sphink)
Make a new task for sweeping unique IDs.

This conflicts with JSCompartment::sweepDebugEnvironments which looks up things in the unique ID table, so I factored this (and breakpoint sweeping) into a separate method that runs first before anything else.
Attachment #8863826 - Flags: review?(sphink)
Everything left that happens on the main thread while parallel tasks are running is related to the JITs (even Zone::beginSweepTypes it seems) so I factored this out into a separate method.
Attachment #8863827 - Flags: review?(sphink)
This adds AutoRunGCSweepTask to factor out a load of boilerplate.

I had to make ~GCParallelTask with whether or not the helper thread lock was held.
Attachment #8863828 - Flags: review?(sphink)
Finally, add separate stats phases for all these different things.
Attachment #8863829 - Flags: review?(sphink)
Attachment #8863774 - Flags: review?(sphink) → review+
Attachment #8863776 - Flags: review?(sphink) → review+
Attachment #8863778 - Flags: review?(sphink) → review+
Comment on attachment 8863779 [details] [diff] [review]
4 - sweep-weak-caches

Review of attachment 8863779 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/jsgc.cpp
@@ +5127,5 @@
> +    })) {
> +        return out;
> +    }
> +
> +    // If we ran out of memory, do all the work now and return and empty list.

*an empty

@@ +5132,5 @@
> +    IterateWeakCaches(rt, [&] (JS::WeakCache<void*>* cache) {
> +        SweepWeakCacheTask(rt, *cache).runFromActiveCooperatingThread(rt);
> +        return true;
> +    });
> +    return WeakCacheTaskVector();

I guess this is ok. All the lambda and functor vector and fallback stuff seems a little complicated, but I guess counting up the weak caches in the sweep group and then using reserve() isn't any better. It still ends up coding the iteration twice.

I tried to think of a way to make template-happy appended and chained iterators, but... never mind. I guess the alternative would be an explicit weak cache iterator that you give a runtime.

Oh well. This works.
Attachment #8863779 - Flags: review?(sphink) → review+
Comment on attachment 8863826 [details] [diff] [review]
5 - sweep-unique-ids

Review of attachment 8863826 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/jsgc.cpp
@@ +5108,5 @@
> +
> +    gcstats::AutoPhase ap(stats(), gcstats::PHASE_SWEEP_COMPARTMENTS);
> +
> +    // Sweep debug environment information. This performs lookups in the Zone's
> +    // unique IDs table and so must not happen in parallel with this.

s/this/sweeping that table/?
Attachment #8863826 - Flags: review?(sphink) → review+
Attachment #8863827 - Flags: review?(sphink) → review+
Comment on attachment 8863828 [details] [diff] [review]
7 - refactor-start-join

Review of attachment 8863828 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/jsgc.cpp
@@ +4970,5 @@
> +MAKE_GC_SWEEP_TASK(SweepRegExpsTask,          gcstats::PHASE_SWEEP_REGEXP);
> +MAKE_GC_SWEEP_TASK(SweepMiscTask,             gcstats::PHASE_SWEEP_MISC);
> +MAKE_GC_SWEEP_TASK(SweepCompressionTasksTask, gcstats::PHASE_SWEEP_MISC);
> +MAKE_GC_SWEEP_TASK(SweepWeakMapsTask,         gcstats::PHASE_SWEEP_MISC);
> +MAKE_GC_SWEEP_TASK(SweepUniqueIdsTask,        gcstats::PHASE_SWEEP_BREAKPOINT);

This patch does kill a lot of boilerplate. Nice!

Though here, I'm starting to wonder what the advantage of this macro is over something like

template <void RunnerFunc(GCRuntime*), gcstats::Phase phase>
class SweepTask : public GCSweepTask {
  void run() override {
    AutoPhase ap(runtime()->gc.stats(), phase);
    RunnerFunc(runtime());
  }
}

static void
SweepAtoms(GCRuntime* rt)
{
   ...
}

.
.
.
AutoRunGCSweepTask<SweepTask<SweepAtoms, gcstats::PHASE_SWEEP_ATOMS>>> sweepAtoms(this, helperLock);

I think I'm mixing up JSRuntime and GCRuntime and probably missing various other bits and pieces. And I'm not sure there's really much of a benefit here. It's just a pretty funky macro, I guess.
Attachment #8863828 - Flags: review?(sphink) → review+
Comment on attachment 8863829 [details] [diff] [review]
8 - fix-stats-phases

Review of attachment 8863829 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/gc/Statistics.cpp
@@ +221,2 @@
>  
>      // Current number of telemetryBuckets is 61. If you insert new phases

Change the 61. Or make it refer to the PHASE_LIMIT one so we don't have to keep changing both.

::: js/src/jsgc.cpp
@@ +4970,5 @@
>  MAKE_GC_SWEEP_TASK(SweepRegExpsTask,          gcstats::PHASE_SWEEP_REGEXP);
>  MAKE_GC_SWEEP_TASK(SweepMiscTask,             gcstats::PHASE_SWEEP_MISC);
> +MAKE_GC_SWEEP_TASK(SweepCompressionTasksTask, gcstats::PHASE_SWEEP_COMPRESSION);
> +MAKE_GC_SWEEP_TASK(SweepWeakMapsTask,         gcstats::PHASE_SWEEP_WEAKMAPS);
> +MAKE_GC_SWEEP_TASK(SweepUniqueIdsTask,        gcstats::PHASE_SWEEP_UNIQUEIDS);

Heh. With all of these unique, we could even

template<> void
SweepTask<PHASE_SWEEP_UNIQUEIDS>::run() { ... }

but... nah.
Attachment #8863829 - Flags: review?(sphink) → review+
Keywords: leave-open
Pushed by jcoppeard@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/02fb52a5071f
Refactor queing arenas for sweeping to use a single loop r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/3d0f582a516e
Sweep weakmaps in parallel with other sweeping r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/1ac60eace76b
Move more miscellaneous sweeping off the main thread r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/a755dec3c1a5
Sweep runtime-wide weak caches as part of the weak cache sweeping task r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/6139e5baee96
Sweep unique IDs in parallel with other sweeping r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/8c42621d4720
Move sweeping JIT-related data into its own method r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/276c2459d415
Add RAII class to start/join a GC sweep task r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/aaa215039794
Add separate stats phases for all the sweep tasks r=sfink
(In reply to Steve Fink [:sfink] [:s:] from comment #9)
> All the lambda and functor vector and fallback stuff
> seems a little complicated, but I guess counting up the weak caches in the
> sweep group and then using reserve() isn't any better.

I rewrote this to use an iterator class like we do for Zones etc, but the result was longer and it wasn't as clear that it was correct as having a iterator function containing a few for loops.

Instead I refactored the current code a little to hopefully make it a bit clearer.
Attachment #8864178 - Flags: review?(sphink)
(In reply to Steve Fink [:sfink] [:s:] from comment #11)
> Though here, I'm starting to wonder what the advantage of this macro is over
> something like
> 
> template <void RunnerFunc(GCRuntime*), gcstats::Phase phase>
> class SweepTask : public GCSweepTask {

This is a great idea.  In fact we can kill GCSweepTask too and have our auto class inherit from GCParallelTask.
Attachment #8864201 - Flags: review?(sphink)
Comment on attachment 8864178 [details] [diff] [review]
9 - improve-weak-cache-iteration

Review of attachment 8864178 [details] [diff] [review]:
-----------------------------------------------------------------

That does read a little better, thanks.
Attachment #8864178 - Flags: review?(sphink) → review+
Comment on attachment 8864201 [details] [diff] [review]
10 - remove-gc-sweep-task

Review of attachment 8864201 [details] [diff] [review]:
-----------------------------------------------------------------

r=me since these are heavyweight enough that going through a function pointer is ok. I was originally thinking that you'd templatize on the exact function to eliminate the indirect call, but this is probably better. (I think it's probably simpler, and the perf overhead doesn't matter.)
Attachment #8864201 - Flags: review?(sphink) → review+
Pushed by jcoppeard@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/2c14238a5a52
Make weak cache iteration more readable r=sfink
https://hg.mozilla.org/integration/mozilla-inbound/rev/b388bdf5bf38
Refactor to remove GCSweepTask and associated macros r=sfink
Keywords: leave-open
https://hg.mozilla.org/mozilla-central/rev/2c14238a5a52
https://hg.mozilla.org/mozilla-central/rev/b388bdf5bf38
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: