diff options
author | paulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-01 00:14:02 +0000 |
---|---|---|
committer | paulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-01 00:14:02 +0000 |
commit | 1ca6df9ae9d23bffa27bb1f5fd19a79a6621939a (patch) | |
tree | a9fea3767e301099e4343fd228209df02143130f /chrome/browser/resource_dispatcher_host.cc | |
parent | 656e3b3857e315a4a6386944fb140ef202580f77 (diff) | |
download | chromium_src-1ca6df9ae9d23bffa27bb1f5fd19a79a6621939a.zip chromium_src-1ca6df9ae9d23bffa27bb1f5fd19a79a6621939a.tar.gz chromium_src-1ca6df9ae9d23bffa27bb1f5fd19a79a6621939a.tar.bz2 |
Eliminate the infinite read loop that can occasionally allow
a large, fast network request to monopolize the IO thread.
This particular bug was tickled by an FTP download where
pause tasks posted to the IO thread from the UI thread were
blocked from running until the FTP transfer was completed,
leading to user noticeable jankiness.
I added histograms to the previous read loop and noticed
that during regular browsing and downloading sessions, the
number of times the loop was traversed was 1 for something
like 99.5% of the time. This leads me to believe that
eliminating the read loop in favor of asynchronous tasks
will not impact performance.
BUG=1270179
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@212 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resource_dispatcher_host.cc')
-rw-r--r-- | chrome/browser/resource_dispatcher_host.cc | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/chrome/browser/resource_dispatcher_host.cc b/chrome/browser/resource_dispatcher_host.cc index c81f9cb..c3f4e91 100644 --- a/chrome/browser/resource_dispatcher_host.cc +++ b/chrome/browser/resource_dispatcher_host.cc @@ -2024,16 +2024,28 @@ void ResourceDispatcherHost::OnReadCompleted(URLRequest* request, return; } - // Keep reading as long as we can. - while (request->status().is_success() && - CompleteRead(request, &bytes_read)) { + if (request->status().is_success() && CompleteRead(request, &bytes_read)) { // The request can be paused if we realize that the renderer is not // servicing messages fast enough. - if (info->pause_count > 0) - break; - - if (!Read(request, &bytes_read)) - break; // IO is pending. + if (info->pause_count == 0 && + Read(request, &bytes_read) && + request->status().is_success()) { + if (bytes_read == 0) { + CompleteRead(request, &bytes_read); + } else { + // Force the next CompleteRead / Read pair to run as a separate task. + // This avoids a fast, large network request from monopolizing the IO + // thread and starving other IO operations from running. + info->paused_read_bytes = bytes_read; + info->is_paused = true; + GlobalRequestID id(info->render_process_host_id, info->request_id); + MessageLoop::current()->PostTask( + FROM_HERE, + method_runner_.NewRunnableMethod( + &ResourceDispatcherHost::ResumeRequest, id)); + return; + } + } } if (PauseRequestIfNeeded(info)) { |