Necko: support sending OnDataAvailable() to other threads: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
Line 1: Line 1:
At the April 2009 Platform work week we had a meeting on making necko support requests from threads other than the main thread.  Here's some design notes on what we came up with.
At the April 2009 Platform work week we had a meeting on making necko support requests from threads other than the main thread.  Here's some design notes on what we came up with.


== Is this even worth implementing given our plans for multiprocess? ==
== Do we actually want to implement this? ==


So one very relevant question:  do we even want to do this, given our move to using multiple processes (see [[Content_Processes]])?
The basic goal here is to allow the off-main-thread HTML 5 parser to get data from the network without having to having to proxy the data to the main thread.  The benefits are greater parallelism and reduced interference between the main thread and the parser thread (resulting in better UI responsiveness).


The API described on this page allows very limited necko access to non-main threads in our current, single process architectureThe primary target is an off-main thread HTML parser.  But if we're going to switch to a multi-process architecture, with the HTML parser in the subprocess(es), there seems to be little point in doing this work, too.  They both achieve better UI/parser response times, and greater parallelism.  The subprocess implementation will also expose a full necko interface to subprocesses, rather than the limited API here.
Now that we are moving towards using multiple processes (see [[Content_Processes]]), there is some question of how useful the solution documented here isIn the long run, we are going to be putting the HTML parser in separate processes rather than threads;  so this solution is at best a temporary one.  But since the API here should be faster to implement than the multi-process one, it might be a useful stopgap implementation for a release or two, until multi-process is ready for prime time.


The only reason I can see for doing the API here is because we can implement it sooner. But since there's just one of me :), it would mean the subprocess implementation would be delayed.
The key question, then, is: just how much performance/responsiveness benefit do we anticipate getting from eliminating proxied network receives, and having the HTML 5 off-thread parser get reads directly?  If this is not a significant win, I'd prefer to focus my attention on developing multiprocess networking.
 
Thoughts on this matter would be appreciated.


== API target:  sending OnDataAvailable() to other threads ==
== API target:  sending OnDataAvailable() to other threads ==

Revision as of 19:15, 6 May 2009

At the April 2009 Platform work week we had a meeting on making necko support requests from threads other than the main thread. Here's some design notes on what we came up with.

Do we actually want to implement this?

The basic goal here is to allow the off-main-thread HTML 5 parser to get data from the network without having to having to proxy the data to the main thread. The benefits are greater parallelism and reduced interference between the main thread and the parser thread (resulting in better UI responsiveness).

Now that we are moving towards using multiple processes (see Content_Processes), there is some question of how useful the solution documented here is. In the long run, we are going to be putting the HTML parser in separate processes rather than threads; so this solution is at best a temporary one. But since the API here should be faster to implement than the multi-process one, it might be a useful stopgap implementation for a release or two, until multi-process is ready for prime time.

The key question, then, is: just how much performance/responsiveness benefit do we anticipate getting from eliminating proxied network receives, and having the HTML 5 off-thread parser get reads directly? If this is not a significant win, I'd prefer to focus my attention on developing multiprocess networking.

Thoughts on this matter would be appreciated.

API target: sending OnDataAvailable() to other threads

In a perfect world, our goal would be an API where any thread could use the full necko interface, and initiate and process network requests completely independently. However, while there's no theoretical reason why necko couldn't be made fully re-entrant, the implementation obstacles involved would be considerable (see notes at end for some details).

Benjamin Smedberg suggested a much more modest goal: that non-main threads be allowed to directly receive the OnDataAvailable() call from the nsIStreamListener interface. All setup of the network channel before this point (and possibly after) would need to be handled on the main thread.

The meeting quickly came to a consensus that something like this would be sufficient for the existing use cases for which a multithreaded necko has been requested: most notably, for an off-main-thread HTML parser to be able to stream in HTML from the network without interfering/delaying the main thread (and vice versa).

There still remain, however, some questions about the exact API:

API Discussion

1) Decision to divert data to other thread should only be made within OnStartRequest().

There seemed to be general agreement that the decision to offload OnDataAvailable() to a different thread should only be possible within OnStartRequest(). By this point, we will have the final channel for the request (i.e. any redirects, auth requests, etc, will have been resolved). We will also have the Content-type of the request, which we will need to determine whether the data should be handled by an off-thread consumer (like the HTML parser) in the first place.

2) How to notify other-thread listener when request is complete?

Two obvious ways come to mind. 1) We could also divert OnStopRequest() to the listener's thread. Or, 2) we could send an additional OnDataAvailable() with data length == 0 to signal the end of the Request. #1 is more intuitive for the programmer; #2 is more conservative, in that the main thread will still receive OnStopRequest. Since compliant nsChannels will need to be modified anyway, no one could think of a good reason not to change them to no longer expect OnStopRequest(), and so #1 is the current winner, pending discovery of any problems with not delivering OnStopReq() to the main thread.

3) Code would need to query both the Channel and any StreamListeners chained between the socket and the target listener, to make sure they are all safe to be switched to a different thread for OnDataAvailable. (We could modify any relevant existing internal listeners to become safe, but since some listeners could come from extensions, we cannot guarantee all listeners will always be safe). Code must be prepared to handle the case where OnDataAvailable cannot be redirected to the desired thread.

Implemention Questions

  • cache: no one seems to know exactly what mods might need to be made to the cache to support multiple simultaneous readers.


Notes: Obstacles to a fully-threaded necko API

  • A large number of classes would need modification: nsURI, nsChannels, IIOService and the various nsIProtocolHandlers.
  • Authorization boxes would need to be popped up from non-main threads
  • Many of the necko APIs have been implemented by Javascript extensions, which would suddenly need to be thread-safe