Open Bug 709072 Opened 13 years ago Updated 2 years ago

Add serial task queues that don't map 1-to-1 to threads and are backed by a pool of worker threads

Categories

(Core :: XPCOM, defect)

defect

Tracking

()

People

(Reporter: hsivonen, Unassigned)

References

Details

To support off-the-main-thread parsing, each instance of nsHtml5StreamParser needs a queue of nsIRunnables that executes the runnables off the main thread serially in the order in which they were added to the queue. That is, an nsIRunnable related to a given nsHtml5StreamParser must not start executing before the previous nsIRunnable related to the same nsHtml5StreamParser has finishes executing.

Currently, all nsHtml5StreamParsers share one thread that serves them all. This satisfies the requirement that each nsHtml5StreamParser has a queue that executes nsIRunnables serially.

There are two problems though:
 1) When there are a lot of CPU cores, the work isn't spread across all available cores.
 2) nsIRunnables related to the frontmost tab have to wait in the queue while nsIRunnables related to background tabs are serviced.

AFAICT, an nsIThreadPool is not the answer, because it seems to start executing tasks in the order the tasks were enqueued but doesn't offer a way for avoiding the overlap in execution of tasks that need to be run serially.

To solve this problem, I propose following:
A new logical unit that manages a number of tasks queues and threads that service those queues. Let's call this e.g. nsIExecutorPool. nsIExecutorPool would have a factory method for obtaining an nsIEventTarget that is serviced by threads managed by the pool and that quarantees that nsIRunnables posted to any given such nsIEventTarget get executed serially.

The application should be able to dynamically tell the nsIExecutor pool which nsIEventTargets pertain to the frontmost tab and which one pertain to background tabs so that priority can be given to servicing the task queues that pertain to the frontmost tab.

An nsIExecutorPool would maintain a multiple worker threads. The number of the threads should probably scale based on the number of otherwise idle CPU cores and should probably not be smaller than 2 so that there can always be at least one high-priority thread and one low-priority thread.

A worker thread would take an nsIRunnable from a task queue that's not having a task run right now, mark the queue as having a task being run, run the task and unmark the queue as having a task run. 

A worker thread running an nsIRunnable from a task queue belonging to a background tab would be given a lower thread scheduling priority than a worker thread running an nsIRunnable from a task queue belonging to a foreground tab.

By having always at least one thread running task for background tabs and always at least one thread running tasks for foreground tabs, the kernel starvation avoidance mechanisms would make sure the background threads don't starve. (They might starve if the worker threads simply always preferred to take a task belonging to a foreground tab.)
IndexedDB's TransactionThreadPool does something very similar to what you describe above, so if we make something more generic maybe we could switch it over too.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.