minor refactoring on dispatching SourceCompressionTask
Categories
(Core :: JavaScript Engine, enhancement, P2)
Tracking
()
Tracking | Status | |
---|---|---|
firefox79 | --- | fixed |
People
(Reporter: allstars.chh, Assigned: allstars.chh)
References
Details
Attachments
(5 files, 6 obsolete files)
The taskSpecs in HelperThread has a Handler function,
https://searchfox.org/mozilla-central/rev/a707541ff423ade0d81cef6488e6ecfa09273886/js/src/vm/HelperThreads.cpp#2466
And there are many similiar code in each handler, like
Assert(idle());
Assert(CanStart...())
currentTask.emplace(..);
// Handle the task
currentTask.reset();
notify(CONSUMER);
We could move those similar code out of the handlers.
The idea is in the case of Tasks are dispatched to XPCOM thread pool, we could reuse the handler.
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 1•5 years ago
|
||
Assignee | ||
Comment 2•5 years ago
|
||
Hi, Jonco
This is the refactoring for HelperThread as I mentioned last week,
can you give it a look?
Also for the Wasm case, I have a WIP patch in bug 1569819.
Comment 3•5 years ago
|
||
(In reply to Yoshi Cheng-Hao Huang [:allstars.chh][:allstarschh] from comment #2)
To be able to use the XPCOM thread pool, we need to split the work that needs to run on the helper thread from the work to select and dispatch tasks. Everything that needs to run on the other thread must be moved into an implementation of RunnableTask::runTask().
This change factors out the work to get the task to run, so this is a good first step. Following on from this, everything in the handleFooTask() methods needs to be either moved into runTask() or into the current thread scheduler. Eventually we should just run the task by calling runTask() in HelperThread::threadLoop.
I'm not sure whether a partial migration to the XPCOM thread pool is going to be possible. There does need to be some kind of scheduling still (as you've seen with the restriction on running as single Wasm job at once) and I don't see how you can have two schedulers at the same time.
Currently scheduling works by picking the next task to run in HelperThread::threadLoop, or waiting for a new task to be queued. That won't work for the XPCOM thread pool because we don't have constantly running threads. Instead we could have a function that checks whether a new task can be scheduled and if so starts it. This would need to be called when every helper thread task is queued and also when every helper thread task finishes. That would let us keep our current scheduling policy.
One direction to approach this from might be to build a simple thread pool for the shell that exposes the same interface as the XPCOM one, and then change the shell to use this first.
Assignee | ||
Comment 4•5 years ago
|
||
Assignee | ||
Comment 5•5 years ago
|
||
Hi Jonco
This is the WIP patch with HelperThreadPool.
This adds a PriorityQueue with js::UniquePtr<RunnableTask>, so when we start an off thread task, like wasm tier2 generator in bug 1569819,
we insert that task into the queue, then the similar threadLoop will fetch the new task from the queue and call runTask() directly.
And PriorityQueue doesn't support move sematics (same for std:priority_queue), so I add a partial specialization for Priorty_Queue with js::UniquePtr.
I haven't run any test yet so it could be very bogus....
could you take a look?
Thanks
Assignee | ||
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Assignee | ||
Comment 6•5 years ago
|
||
Assignee | ||
Comment 7•5 years ago
|
||
Hi Jonco
This version I added some check before dispatching the task, please check js::StartOffThreadWasmTier2Generator for detail.
It will check if we have avaialble thread and this task could be dispatched, and if so, we call HelperThreadTaskCallback to dispatch it.
Meanwhile there's a threadLoopNew() and canDispatch.*Task() functions, which are similar to original threadLoop() and canStart.*Task()
I'll try to merge them later.
So far the task dispatched to SM HelperThreads still uses the same way, we push to the corresponding task queue, and HelperThread checks getHighestPriorityTask() and run it. (see threadLoopNew())
For XPCOM thread we make sure there are still available threads and the task doesn't exceed its limit, then we dispatch the getHighestPriorityTask() to XPCOM thread pool, and when the RunnableTask is about to finished, we call a callback in GlobalHelperThreadState to see if there's another high priority task, and if there is, we dispatch the next high priority task again.
Could you check this?
Thanks
Assignee | ||
Updated•5 years ago
|
Assignee | ||
Comment 8•4 years ago
|
||
Assignee | ||
Comment 9•4 years ago
|
||
Updated•4 years ago
|
Assignee | ||
Comment 10•4 years ago
|
||
After fixed bug 1634720 I went back to review my patches, and found one simpler way to implement this. So far this is still WIP, but at least the try on linux64(debug + opt) are all green. There're still some ongoing patches will be added.
Comment 11•4 years ago
|
||
(In reply to Yoshi Cheng-Hao Huang [:allstars.chh][:allstarschh] from comment #10)
I'm not sure about this approach. If I understand correctly, this runs our current helper thread loop in an XPCOM runnable task. This won't play fair with other users of the thread pool that may be starved if we continually run tasks.
Assignee | ||
Comment 12•4 years ago
|
||
(In reply to Jon Coppeard (:jonco) from comment #11)
I'm not sure about this approach. If I understand correctly, this runs our current helper thread loop in an XPCOM runnable task. This won't play fair with other users of the thread pool that may be starved if we continually run tasks.
Yes, the HelperThread running on XPCOM thread will keep running the tasks until all the tasks are executed. Then the thread will return to HelperThreadPool.
I thought this was okay because normally SM dispatches more than 1 SourceComressionTasks to HelperThreads.
I'll update the patch to let it run only 1 task from queue, once the task is finished it will check if the queue is empty, if not empty it will schedule another RunnableTask to XPCOM thread pool.
Comment 13•4 years ago
|
||
That would be better but I'm still not sure this is the right approach. Really we need to have a separate abstraction for a task than a thread.
Assignee | ||
Comment 14•4 years ago
|
||
Assignee | ||
Comment 15•4 years ago
|
||
Added a mShutdown to prevent thread race and leak when nsThreadPool is shutdown.
This is needed because the dispatch() will be called on a non-main
thread.
Updated•4 years ago
|
Updated•4 years ago
|
Assignee | ||
Comment 16•4 years ago
|
||
Jonco, can you check the patch and give me some comments?
Thanks
Comment 17•4 years ago
•
|
||
(In reply to Yoshi Cheng-Hao Huang [:allstars.chh][:allstarschh] from comment #16)
Comments in phabricator.
Assignee | ||
Comment 18•4 years ago
|
||
Jonco, I just update the code with your comments addressed, could you check it?
Thanks
Updated•4 years ago
|
Assignee | ||
Comment 19•4 years ago
|
||
ni? jonco again for the updated patches, thanks
Assignee | ||
Comment 20•4 years ago
|
||
Assignee | ||
Comment 21•4 years ago
|
||
https://phabricator.services.mozilla.com/D78461 moves the code inside runTask,
however it still has some asan failures
https://treeherder.mozilla.org/#/jobs?repo=try&revision=2a4e213567f7c6a30e1efd16977d80e10d535052&selectedTaskRun=e1q_9sOOSxmLVLOnhbaIPQ-0
The reason is originally "append to compressionFinishList" and currentTask.reset() will be executed atomically, but now there's an extra unlock before currentTask.reset(), and other thread executes AttachToFinishList and deletes the pointer, and now 3rd thread calls CancelOffThreadCompressionTask and try to get helper.compressionTask(), but the pointer has been deleted.
Assignee | ||
Comment 22•4 years ago
|
||
Hi Jonco
Or does it make sense to call SourceCompressionTask->complete() after runTask on a helper thread?
Now I got a TSAN failure, one is a helper thread calling complete(), and the main thread is calling trace().
Assignee | ||
Comment 23•4 years ago
|
||
fixed to heap-use-after-free problem by delaying the timing when the SourceCompresionsTask is release from compressionFinishedList.
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Assignee | ||
Comment 24•4 years ago
|
||
So far I found there are some tests on try will have leak, still figuring out where the leak is from.
I've tried to make all subclasses of RunnableTasks like SourceCompressionTask, ParseTask, wasm::Tier2Generator, IonCompileTask .... to inherit HelperTask, but IonCompileTasks seems to have more problems (I found many assertions related to IonScript, IonCompileTask in my try push), so in the end I've only made SourceComressionTask inherit HelperTask, other tasks remain the same (inherit RunnableTask).
Assignee | ||
Comment 25•4 years ago
|
||
(In reply to Yoshi Cheng-Hao Huang [:allstars.chh][:allstarschh] from comment #21)
https://phabricator.services.mozilla.com/D78461 moves the code inside runTask,
however it still has some asan failures
https://treeherder.mozilla.org/#/jobs?repo=try&revision=2a4e213567f7c6a30e1efd16977d80e10d535052&selectedTaskRun=e1q_9sOOSxmLVLOnhbaIPQ-0The reason is originally "append to compressionFinishList" and currentTask.reset() will be executed atomically, but now there's an extra unlock before currentTask.reset(), and other thread executes AttachToFinishList and deletes the pointer, and now 3rd thread calls CancelOffThreadCompressionTask and try to get helper.compressionTask(), but the pointer has been deleted.
Updated the patch with jonco's comment https://phabricator.services.mozilla.com/D78461#inline-456075
now runTaskImpl takes a lock can fix this.
(In reply to Yoshi Cheng-Hao Huang [:allstars.chh][:allstarschh] from comment #24)
So far I found there are some tests on try will have leak, still figuring out where the leak is from.
The leak is calling nsThreadPool::Dispatch while it's shutdown, filed the bug 1645153
Jonco, can you look the latest patch again? Thanks
Assignee | ||
Comment 26•4 years ago
|
||
Updated•4 years ago
|
Assignee | ||
Comment 27•4 years ago
|
||
Updated•4 years ago
|
Updated•4 years ago
|
Assignee | ||
Comment 28•4 years ago
|
||
revert https://phabricator.services.mozilla.com/D74736
In handleCompression the task will be moved to compressionFinishedList
and later main thread will use compressionFinishedList to do the
finishing.
So we need to release the ownership otherwise the task will be
released by HelperThreadTaskHandler.
Updated•4 years ago
|
Assignee | ||
Comment 29•4 years ago
|
||
Updated the part 3 patch, so we don't dispatch to XPCOM at the moment.
Updated•4 years ago
|
Assignee | ||
Updated•4 years ago
|
Assignee | ||
Comment 30•4 years ago
•
|
||
We only want to land the refactoring parts in this bug atm.
https://phabricator.services.mozilla.com/D78461
https://phabricator.services.mozilla.com/D79420
Comment 31•4 years ago
|
||
Comment 32•4 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/7a81a85d9881
https://hg.mozilla.org/mozilla-central/rev/8050fb033d92
Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Description
•