OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading |
6 | 6 |
7 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
8 | 8 |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 | 10 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 | 161 |
162 namespace content { | 162 namespace content { |
163 | 163 |
164 namespace { | 164 namespace { |
165 | 165 |
166 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; | 166 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; |
167 | 167 |
168 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates | 168 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates |
169 const int kUpdateLoadStatesIntervalMsec = 250; | 169 const int kUpdateLoadStatesIntervalMsec = 250; |
170 | 170 |
171 // The interval for calls to RecordOutstandingRequestsStats. | |
172 const int kRecordOutstandingRequestsStatsIntervalMsec = 60000; | |
173 | |
171 // Maximum byte "cost" of all the outstanding requests for a renderer. | 174 // Maximum byte "cost" of all the outstanding requests for a renderer. |
172 // See declaration of |max_outstanding_requests_cost_per_process_| for details. | 175 // See declaration of |max_outstanding_requests_cost_per_process_| for details. |
173 // This bound is 25MB, which allows for around 6000 outstanding requests. | 176 // This bound is 25MB, which allows for around 6000 outstanding requests. |
174 const int kMaxOutstandingRequestsCostPerProcess = 26214400; | 177 const int kMaxOutstandingRequestsCostPerProcess = 26214400; |
175 | 178 |
176 // The number of milliseconds after noting a user gesture that we will | 179 // The number of milliseconds after noting a user gesture that we will |
177 // tag newly-created URLRequest objects with the | 180 // tag newly-created URLRequest objects with the |
178 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary | 181 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary |
179 // guess at how long to expect direct impact from a user gesture, but | 182 // guess at how long to expect direct impact from a user gesture, but |
180 // this should be OK as the load flag is a best-effort thing only, | 183 // this should be OK as the load flag is a best-effort thing only, |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 : request_id_(-1), | 335 : request_id_(-1), |
333 is_shutdown_(false), | 336 is_shutdown_(false), |
334 num_in_flight_requests_(0), | 337 num_in_flight_requests_(0), |
335 max_num_in_flight_requests_(base::SharedMemory::GetHandleLimit()), | 338 max_num_in_flight_requests_(base::SharedMemory::GetHandleLimit()), |
336 max_num_in_flight_requests_per_process_(static_cast<int>( | 339 max_num_in_flight_requests_per_process_(static_cast<int>( |
337 max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)), | 340 max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)), |
338 max_outstanding_requests_cost_per_process_( | 341 max_outstanding_requests_cost_per_process_( |
339 kMaxOutstandingRequestsCostPerProcess), | 342 kMaxOutstandingRequestsCostPerProcess), |
340 largest_outstanding_request_count_seen_(0), | 343 largest_outstanding_request_count_seen_(0), |
341 largest_outstanding_request_per_process_count_seen_(0), | 344 largest_outstanding_request_per_process_count_seen_(0), |
345 peak_outstanding_request_count_(0), | |
346 peak_outstanding_request_count_multitab_(0), | |
342 delegate_(nullptr), | 347 delegate_(nullptr), |
343 loader_delegate_(nullptr), | 348 loader_delegate_(nullptr), |
344 allow_cross_origin_auth_prompt_(false), | 349 allow_cross_origin_auth_prompt_(false), |
345 create_download_handler_intercept_(download_handler_intercept), | 350 create_download_handler_intercept_(download_handler_intercept), |
346 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 351 main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
347 io_thread_task_runner_(io_thread_runner), | 352 io_thread_task_runner_(io_thread_runner), |
348 experimental_web_features_enabled_( | 353 experimental_web_features_enabled_( |
349 base::CommandLine::ForCurrentProcess()->HasSwitch( | 354 base::CommandLine::ForCurrentProcess()->HasSwitch( |
350 switches::kEnableExperimentalWebPlatformFeatures)) { | 355 switches::kEnableExperimentalWebPlatformFeatures)) { |
351 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); | 356 DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); |
352 DCHECK(!g_resource_dispatcher_host); | 357 DCHECK(!g_resource_dispatcher_host); |
353 g_resource_dispatcher_host = this; | 358 g_resource_dispatcher_host = this; |
354 | 359 |
355 ANNOTATE_BENIGN_RACE( | 360 ANNOTATE_BENIGN_RACE( |
356 &last_user_gesture_time_, | 361 &last_user_gesture_time_, |
357 "We don't care about the precise value, see http://crbug.com/92889"); | 362 "We don't care about the precise value, see http://crbug.com/92889"); |
358 | 363 |
359 io_thread_task_runner_->PostTask( | 364 io_thread_task_runner_->PostTask( |
360 FROM_HERE, | 365 FROM_HERE, |
361 base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this))); | 366 base::Bind(&ResourceDispatcherHostImpl::OnInit, base::Unretained(this))); |
362 | 367 |
363 update_load_states_timer_.reset(new base::RepeatingTimer()); | 368 update_load_states_timer_.reset(new base::RepeatingTimer()); |
369 record_outstanding_requests_stats_timer_.reset(new base::RepeatingTimer()); | |
364 } | 370 } |
365 | 371 |
366 // The default ctor is only used by unittests. It is reasonable to assume that | 372 // The default ctor is only used by unittests. It is reasonable to assume that |
367 // the main thread and the IO thread are the same for unittests. | 373 // the main thread and the IO thread are the same for unittests. |
368 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() | 374 ResourceDispatcherHostImpl::ResourceDispatcherHostImpl() |
369 : ResourceDispatcherHostImpl(CreateDownloadHandlerIntercept(), | 375 : ResourceDispatcherHostImpl(CreateDownloadHandlerIntercept(), |
370 base::ThreadTaskRunnerHandle::Get()) {} | 376 base::ThreadTaskRunnerHandle::Get()) {} |
371 | 377 |
372 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { | 378 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { |
373 DCHECK(outstanding_requests_stats_map_.empty()); | 379 DCHECK(outstanding_requests_stats_map_.empty()); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 | 588 |
583 const net::URLRequestJobFactory* job_factory = | 589 const net::URLRequestJobFactory* job_factory = |
584 info->GetContext()->GetRequestContext()->job_factory(); | 590 info->GetContext()->GetRequestContext()->job_factory(); |
585 if (!url.is_valid() || job_factory->IsHandledProtocol(url.scheme())) | 591 if (!url.is_valid() || job_factory->IsHandledProtocol(url.scheme())) |
586 return false; | 592 return false; |
587 | 593 |
588 return delegate_->HandleExternalProtocol(url, info); | 594 return delegate_->HandleExternalProtocol(url, info); |
589 } | 595 } |
590 | 596 |
591 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { | 597 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { |
592 // Make sure we have the load state monitor running. | 598 // Make sure we have the load state monitors running. |
593 if (!update_load_states_timer_->IsRunning() && | 599 if (!update_load_states_timer_->IsRunning() && |
594 scheduler_->HasLoadingClients()) { | 600 scheduler_->HasLoadingClients()) { |
595 update_load_states_timer_->Start( | 601 update_load_states_timer_->Start( |
596 FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), | 602 FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), |
597 this, &ResourceDispatcherHostImpl::UpdateLoadInfo); | 603 this, &ResourceDispatcherHostImpl::UpdateLoadInfo); |
598 } | 604 } |
605 if (!record_outstanding_requests_stats_timer_->IsRunning()) { | |
606 record_outstanding_requests_stats_timer_->Start( | |
607 FROM_HERE, | |
608 TimeDelta::FromMilliseconds( | |
609 kRecordOutstandingRequestsStatsIntervalMsec), | |
610 this, &ResourceDispatcherHostImpl::RecordOutstandingRequestsStats); | |
611 } | |
599 } | 612 } |
600 | 613 |
601 void ResourceDispatcherHostImpl::DidReceiveRedirect( | 614 void ResourceDispatcherHostImpl::DidReceiveRedirect( |
602 ResourceLoader* loader, | 615 ResourceLoader* loader, |
603 const GURL& new_url, | 616 const GURL& new_url, |
604 ResourceResponse* response) { | 617 ResourceResponse* response) { |
605 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | 618 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
606 if (delegate_) { | 619 if (delegate_) { |
607 delegate_->OnRequestRedirected( | 620 delegate_->OnRequestRedirected( |
608 new_url, loader->request(), info->GetContext(), response); | 621 new_url, loader->request(), info->GetContext(), response); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
777 void ResourceDispatcherHostImpl::OnInit() { | 790 void ResourceDispatcherHostImpl::OnInit() { |
778 scheduler_.reset(new ResourceScheduler); | 791 scheduler_.reset(new ResourceScheduler); |
779 } | 792 } |
780 | 793 |
781 void ResourceDispatcherHostImpl::OnShutdown() { | 794 void ResourceDispatcherHostImpl::OnShutdown() { |
782 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); | 795 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); |
783 | 796 |
784 is_shutdown_ = true; | 797 is_shutdown_ = true; |
785 pending_loaders_.clear(); | 798 pending_loaders_.clear(); |
786 | 799 |
787 // Make sure we shutdown the timer now, otherwise by the time our destructor | 800 // Make sure we shutdown the timers now, otherwise by the time our destructor |
788 // runs if the timer is still running the Task is deleted twice (once by | 801 // runs if the timer is still running the Task is deleted twice (once by |
789 // the MessageLoop and the second time by RepeatingTimer). | 802 // the MessageLoop and the second time by RepeatingTimer). |
790 update_load_states_timer_.reset(); | 803 update_load_states_timer_.reset(); |
804 record_outstanding_requests_stats_timer_.reset(); | |
791 | 805 |
792 // Clear blocked requests if any left. | 806 // Clear blocked requests if any left. |
793 // Note that we have to do this in 2 passes as we cannot call | 807 // Note that we have to do this in 2 passes as we cannot call |
794 // CancelBlockedRequestsForRoute while iterating over | 808 // CancelBlockedRequestsForRoute while iterating over |
795 // blocked_loaders_map_, as it modifies it. | 809 // blocked_loaders_map_, as it modifies it. |
796 std::set<GlobalFrameRoutingId> ids; | 810 std::set<GlobalFrameRoutingId> ids; |
797 for (const auto& blocked_loaders : blocked_loaders_map_) { | 811 for (const auto& blocked_loaders : blocked_loaders_map_) { |
798 std::pair<std::set<GlobalFrameRoutingId>::iterator, bool> result = | 812 std::pair<std::set<GlobalFrameRoutingId>::iterator, bool> result = |
799 ids.insert(blocked_loaders.first); | 813 ids.insert(blocked_loaders.first); |
800 // We should not have duplicates. | 814 // We should not have duplicates. |
(...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1962 } | 1976 } |
1963 | 1977 |
1964 if (stats.num_requests > | 1978 if (stats.num_requests > |
1965 largest_outstanding_request_per_process_count_seen_) { | 1979 largest_outstanding_request_per_process_count_seen_) { |
1966 largest_outstanding_request_per_process_count_seen_ = stats.num_requests; | 1980 largest_outstanding_request_per_process_count_seen_ = stats.num_requests; |
1967 UMA_HISTOGRAM_COUNTS_1M( | 1981 UMA_HISTOGRAM_COUNTS_1M( |
1968 "Net.ResourceDispatcherHost.OutstandingRequests.PerProcess", | 1982 "Net.ResourceDispatcherHost.OutstandingRequests.PerProcess", |
1969 largest_outstanding_request_per_process_count_seen_); | 1983 largest_outstanding_request_per_process_count_seen_); |
1970 } | 1984 } |
1971 | 1985 |
1986 if (num_in_flight_requests_ > peak_outstanding_request_count_) { | |
1987 peak_outstanding_request_count_ = num_in_flight_requests_; | |
1988 } | |
1989 | |
1990 if (HasRequestsFromMultipleActiveProcesses() && | |
1991 num_in_flight_requests_ > peak_outstanding_request_count_multitab_) { | |
1992 peak_outstanding_request_count_multitab_ = num_in_flight_requests_; | |
1993 } | |
1994 | |
1972 return stats; | 1995 return stats; |
1973 } | 1996 } |
1974 | 1997 |
1975 bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest( | 1998 bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest( |
1976 net::URLRequest* request) { | 1999 net::URLRequest* request) { |
1977 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); | 2000 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request); |
1978 OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, info); | 2001 OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, info); |
1979 | 2002 |
1980 if (stats.num_requests > max_num_in_flight_requests_per_process_) | 2003 if (stats.num_requests > max_num_in_flight_requests_per_process_) |
1981 return false; | 2004 return false; |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2490 // We need to be able to compare all requests to find the most important one | 2513 // We need to be able to compare all requests to find the most important one |
2491 // per tab. Since some requests may be navigation requests and we don't have | 2514 // per tab. Since some requests may be navigation requests and we don't have |
2492 // their render frame routing IDs yet (which is what we have for subresource | 2515 // their render frame routing IDs yet (which is what we have for subresource |
2493 // requests), we must go to the UI thread and compare the requests using their | 2516 // requests), we must go to the UI thread and compare the requests using their |
2494 // WebContents. | 2517 // WebContents. |
2495 main_thread_task_runner_->PostTask( | 2518 main_thread_task_runner_->PostTask( |
2496 FROM_HERE, | 2519 FROM_HERE, |
2497 base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos))); | 2520 base::Bind(UpdateLoadStateOnUI, loader_delegate_, base::Passed(&infos))); |
2498 } | 2521 } |
2499 | 2522 |
2523 void ResourceDispatcherHostImpl::RecordOutstandingRequestsStats() { | |
2524 if (peak_outstanding_request_count_ != 0) { | |
2525 UMA_HISTOGRAM_COUNTS_1M( | |
2526 "Net.ResourceDispatcherHost.PeakOutstandingRequests", | |
2527 peak_outstanding_request_count_); | |
2528 peak_outstanding_request_count_ = num_in_flight_requests_; | |
kinuko
2017/06/21 04:00:10
Intuitively I feel this should be reset to 0 becau
Kunihiko Sakamoto
2017/06/21 05:25:32
My intuition is that if there are n outstanding re
kinuko
2017/06/21 07:06:48
Hm, ok I think that makes sense.
| |
2529 } | |
2530 | |
2531 if (peak_outstanding_request_count_multitab_ != 0) { | |
2532 UMA_HISTOGRAM_COUNTS_1M( | |
2533 "Net.ResourceDispatcherHost.PeakOutstandingRequests.MultiTabLoading", | |
kinuko
2017/06/21 04:00:10
The map we rely on groups requests per-process rat
Kunihiko Sakamoto
2017/06/21 05:25:32
Yeah, you're right. Renamed the suffix to 'Multipl
kinuko
2017/06/21 07:06:48
We could use routing_id to gather per-tab stats, h
| |
2534 peak_outstanding_request_count_multitab_); | |
2535 peak_outstanding_request_count_multitab_ = | |
2536 HasRequestsFromMultipleActiveProcesses() ? num_in_flight_requests_ : 0; | |
2537 } | |
2538 } | |
2539 | |
2500 void ResourceDispatcherHostImpl::BlockRequestsForRoute( | 2540 void ResourceDispatcherHostImpl::BlockRequestsForRoute( |
2501 const GlobalFrameRoutingId& global_routing_id) { | 2541 const GlobalFrameRoutingId& global_routing_id) { |
2502 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); | 2542 DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); |
2503 DCHECK(blocked_loaders_map_.find(global_routing_id) == | 2543 DCHECK(blocked_loaders_map_.find(global_routing_id) == |
2504 blocked_loaders_map_.end()) | 2544 blocked_loaders_map_.end()) |
2505 << "BlockRequestsForRoute called multiple time for the same RFH"; | 2545 << "BlockRequestsForRoute called multiple time for the same RFH"; |
2506 blocked_loaders_map_[global_routing_id] = | 2546 blocked_loaders_map_[global_routing_id] = |
2507 base::MakeUnique<BlockedLoadersList>(); | 2547 base::MakeUnique<BlockedLoadersList>(); |
2508 } | 2548 } |
2509 | 2549 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2699 is_content_initiated, true, is_new_request, | 2739 is_content_initiated, true, is_new_request, |
2700 &throttles); | 2740 &throttles); |
2701 if (!throttles.empty()) { | 2741 if (!throttles.empty()) { |
2702 handler.reset(new ThrottlingResourceHandler(std::move(handler), request, | 2742 handler.reset(new ThrottlingResourceHandler(std::move(handler), request, |
2703 std::move(throttles))); | 2743 std::move(throttles))); |
2704 } | 2744 } |
2705 } | 2745 } |
2706 return handler; | 2746 return handler; |
2707 } | 2747 } |
2708 | 2748 |
2749 bool ResourceDispatcherHostImpl::HasRequestsFromMultipleActiveProcesses() { | |
2750 if (outstanding_requests_stats_map_.size() < 2) | |
2751 return false; | |
2752 | |
2753 int active_processes = 0; | |
2754 for (auto iter = outstanding_requests_stats_map_.begin(); | |
2755 iter != outstanding_requests_stats_map_.end(); ++iter) { | |
2756 if (iter->second.num_requests > 2) { | |
2757 active_processes++; | |
2758 if (active_processes >= 2) | |
2759 return true; | |
2760 } | |
2761 } | |
2762 return false; | |
2763 } | |
2764 | |
2709 } // namespace content | 2765 } // namespace content |
OLD | NEW |