| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/performance_manager/public/chrome_browser_main_extra_parts_performance_manager.h" |
| |
| #include <memory> |
| |
| #include "base/feature_list.h" |
| #include "base/functional/bind.h" |
| #include "base/power_monitor/battery_state_sampler.h" |
| #include "base/power_monitor/power_monitor_buildflags.h" |
| #include "base/system/sys_info.h" |
| #include "base/time/default_tick_clock.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/performance_manager/browser_child_process_watcher.h" |
| #include "chrome/browser/performance_manager/decorators/frozen_frame_aggregator.h" |
| #include "chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.h" |
| #include "chrome/browser/performance_manager/decorators/page_aggregator.h" |
| #include "chrome/browser/performance_manager/decorators/page_live_state_decorator_delegate_impl.h" |
| #include "chrome/browser/performance_manager/metrics/memory_pressure_metrics.h" |
| #include "chrome/browser/performance_manager/metrics/metrics_provider_desktop.h" |
| #include "chrome/browser/performance_manager/metrics/page_timeline_monitor.h" |
| #include "chrome/browser/performance_manager/observers/page_load_metrics_observer.h" |
| #include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h" |
| #include "chrome/browser/performance_manager/policies/policy_features.h" |
| #include "chrome/browser/performance_manager/policies/working_set_trimmer_policy.h" |
| #include "chrome/browser/performance_manager/user_tuning/profile_discard_opt_out_list_helper.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/sessions/session_restore.h" |
| #include "components/performance_manager/embedder/graph_features.h" |
| #include "components/performance_manager/embedder/performance_manager_lifetime.h" |
| #include "components/performance_manager/embedder/performance_manager_registry.h" |
| #include "components/performance_manager/graph/policies/bfcache_policy.h" |
| #include "components/performance_manager/performance_manager_feature_observer_client.h" |
| #include "components/performance_manager/public/decorators/page_live_state_decorator.h" |
| #include "components/performance_manager/public/decorators/page_load_tracker_decorator_helper.h" |
| #include "components/performance_manager/public/decorators/process_metrics_decorator.h" |
| #include "components/performance_manager/public/features.h" |
| #include "components/performance_manager/public/graph/graph.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/common/content_features.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| #include "base/allocator/buildflags.h" |
| #include "chromeos/dbus/power/power_manager_client.h" |
| #include "components/performance_manager/power/battery_level_provider_chromeos.h" |
| #include "components/performance_manager/power/dbus_power_manager_sampling_event_source.h" |
| |
| #if defined(ARCH_CPU_X86_64) |
| #include "chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h" |
| #endif // defined(ARCH_CPU_X86_64) |
| |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| #include "chrome/browser/performance_manager/policies/oom_score_policy_lacros.h" |
| #endif // BUILDFLAG(IS_CHROMEOS_LACROS) |
| |
| #if BUILDFLAG(ENABLE_EXTENSIONS) |
| #include "chrome/browser/performance_manager/extension_watcher.h" |
| #endif |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| #include "chrome/browser/performance_manager/mechanisms/page_freezer.h" |
| #include "chrome/browser/performance_manager/policies/heuristic_memory_saver_policy.h" |
| #include "chrome/browser/performance_manager/policies/high_efficiency_mode_policy.h" |
| #include "chrome/browser/performance_manager/policies/page_discarding_helper.h" |
| #include "chrome/browser/performance_manager/policies/page_freezing_policy.h" |
| #include "chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h" |
| #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" |
| #include "chrome/browser/performance_manager/user_tuning/user_performance_tuning_notifier.h" |
| #include "chrome/browser/tab_contents/form_interaction_tab_helper.h" |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| namespace { |
| ChromeBrowserMainExtraPartsPerformanceManager* g_instance = nullptr; |
| } |
| |
| ChromeBrowserMainExtraPartsPerformanceManager:: |
| ChromeBrowserMainExtraPartsPerformanceManager() |
| : feature_observer_client_( |
| std::make_unique< |
| performance_manager::PerformanceManagerFeatureObserverClient>()) { |
| DCHECK(!g_instance); |
| g_instance = this; |
| } |
| |
| ChromeBrowserMainExtraPartsPerformanceManager:: |
| ~ChromeBrowserMainExtraPartsPerformanceManager() { |
| DCHECK_EQ(this, g_instance); |
| g_instance = nullptr; |
| } |
| |
| // static |
| ChromeBrowserMainExtraPartsPerformanceManager* |
| ChromeBrowserMainExtraPartsPerformanceManager::GetInstance() { |
| return g_instance; |
| } |
| |
| // static |
| void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators( |
| performance_manager::Graph* graph) { |
| graph->PassToGraph(std::make_unique<performance_manager::PageAggregator>()); |
| graph->PassToGraph( |
| std::make_unique<performance_manager::FrozenFrameAggregator>()); |
| graph->PassToGraph( |
| std::make_unique<performance_manager::ProcessMetricsDecorator>()); |
| graph->PassToGraph( |
| std::make_unique<performance_manager::PageLiveStateDecorator>( |
| performance_manager::PageLiveStateDelegateImpl::Create())); |
| |
| if (performance_manager::policies::WorkingSetTrimmerPolicy:: |
| PlatformSupportsWorkingSetTrim()) { |
| graph->PassToGraph(performance_manager::policies::WorkingSetTrimmerPolicy:: |
| CreatePolicyForPlatform()); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| #if defined(ARCH_CPU_X86_64) |
| if (performance_manager::policies::UserspaceSwapPolicy:: |
| UserspaceSwapSupportedAndEnabled()) { |
| graph->PassToGraph( |
| std::make_unique<performance_manager::policies::UserspaceSwapPolicy>()); |
| } |
| #endif // defined(ARCH_CPU_X86_64) |
| |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| #if BUILDFLAG(IS_CHROMEOS_LACROS) |
| graph->PassToGraph( |
| std::make_unique<performance_manager::policies::OomScorePolicyLacros>()); |
| #endif // BUILDFLAG(IS_CHROMEOS_LACROS) |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| graph->PassToGraph(FormInteractionTabHelper::CreateGraphObserver()); |
| |
| graph->PassToGraph( |
| std::make_unique<performance_manager::policies::PageDiscardingHelper>()); |
| |
| #if URGENT_DISCARDING_FROM_PERFORMANCE_MANAGER() |
| if (base::FeatureList::IsEnabled( |
| performance_manager::features::kUrgentPageDiscarding)) { |
| graph->PassToGraph( |
| std::make_unique< |
| performance_manager::policies::UrgentPageDiscardingPolicy>()); |
| } |
| #endif // URGENT_DISCARDING_FROM_PERFORMANCE_MANAGER() |
| |
| if (base::FeatureList::IsEnabled( |
| performance_manager::features:: |
| kBackgroundTabLoadingFromPerformanceManager)) { |
| graph->PassToGraph( |
| std::make_unique< |
| performance_manager::policies::BackgroundTabLoadingPolicy>( |
| base::BindRepeating([]() { |
| content::GetUIThreadTaskRunner({})->PostTask( |
| FROM_HERE, |
| base::BindOnce( |
| &SessionRestore::OnTabLoaderFinishedLoadingTabs)); |
| }))); |
| } |
| |
| // The freezing policy isn't enabled on Android yet as it doesn't play well |
| // with the freezing logic already in place in renderers. This logic should be |
| // moved to PerformanceManager, this is tracked in https://crbug.com/1156803. |
| graph->PassToGraph( |
| std::make_unique<performance_manager::policies::PageFreezingPolicy>()); |
| |
| if (base::FeatureList::IsEnabled( |
| performance_manager::features::kHeuristicMemorySaver)) { |
| graph->PassToGraph( |
| std::make_unique< |
| performance_manager::policies::HeuristicMemorySaverPolicy>()); |
| } else { |
| graph->PassToGraph( |
| std::make_unique< |
| performance_manager::policies::HighEfficiencyModePolicy>()); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| graph->PassToGraph( |
| std::make_unique<performance_manager::metrics::MemoryPressureMetrics>()); |
| |
| if (base::FeatureList::IsEnabled( |
| performance_manager::features::kPageTimelineMonitor)) { |
| graph->PassToGraph( |
| std::make_unique<performance_manager::metrics::PageTimelineMonitor>()); |
| } |
| |
| if (base::FeatureList::IsEnabled( |
| performance_manager::features::kBFCachePerformanceManagerPolicy)) { |
| graph->PassToGraph( |
| std::make_unique<performance_manager::policies::BFCachePolicy>()); |
| } |
| } |
| |
| content::FeatureObserverClient* |
| ChromeBrowserMainExtraPartsPerformanceManager::GetFeatureObserverClient() { |
| return feature_observer_client_.get(); |
| } |
| |
| void ChromeBrowserMainExtraPartsPerformanceManager::PostCreateThreads() { |
| performance_manager_lifetime_ = |
| std::make_unique<performance_manager::PerformanceManagerLifetime>( |
| performance_manager::GraphFeatures::WithDefault(), |
| base::BindOnce(&ChromeBrowserMainExtraPartsPerformanceManager:: |
| CreatePoliciesAndDecorators)); |
| browser_child_process_watcher_ = |
| std::make_unique<performance_manager::BrowserChildProcessWatcher>(); |
| browser_child_process_watcher_->Initialize(); |
| |
| // There are no existing loaded profiles. |
| DCHECK(g_browser_process->profile_manager()->GetLoadedProfiles().empty()); |
| |
| g_browser_process->profile_manager()->AddObserver(this); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| profile_discard_opt_out_list_helper_ = std::make_unique< |
| performance_manager::user_tuning::ProfileDiscardOptOutListHelper>(); |
| // Create the UserPerformanceTuningManager here so that early UI code can |
| // register observers, but only start it in PreMainMessageLoopRun because it |
| // requires the HostFrameSinkManager to exist. |
| uint64_t system_memory_kb = base::SysInfo::AmountOfPhysicalMemory() / 1024; |
| user_performance_tuning_manager_ = base::WrapUnique( |
| new performance_manager::user_tuning::UserPerformanceTuningManager( |
| g_browser_process->local_state(), |
| std::make_unique< |
| performance_manager::user_tuning::UserPerformanceTuningNotifier>( |
| base::WrapUnique(new performance_manager::user_tuning:: |
| UserPerformanceTuningManager:: |
| UserPerformanceTuningReceiverImpl), |
| /*resident_set_threshold_kb=*/system_memory_kb * 100 / |
| performance_manager::user_tuning:: |
| UserPerformanceTuningNotifier:: |
| kMemoryPercentThresholdForPromo, |
| /*tab_count_threshold=*/ |
| performance_manager::user_tuning::UserPerformanceTuningNotifier:: |
| kTabCountThresholdForPromo))); |
| #endif |
| |
| page_load_metrics_observer_ = |
| std::make_unique<performance_manager::PageLoadMetricsObserver>(); |
| page_live_state_data_helper_ = |
| std::make_unique<performance_manager::PageLiveStateDecoratorHelper>(); |
| page_load_tracker_decorator_helper_ = |
| std::make_unique<performance_manager::PageLoadTrackerDecoratorHelper>(); |
| #if BUILDFLAG(ENABLE_EXTENSIONS) |
| extension_watcher_ = |
| std::make_unique<performance_manager::ExtensionWatcher>(); |
| #endif |
| |
| // Some browser tests need to control how the battery state behaves, so they |
| // install a test `BatteryStateSampler` before browser setup. |
| if (!base::BatteryStateSampler::HasTestingInstance()) { |
| // The ChromeOS `BatteryLevelProvider` and `SamplingEventSource` |
| // implementations are in `components` for dependency reasons, so they need |
| // to be created here and passed in explicitly to `BatteryStateSampler`. |
| // TODO(crbug.com/1373560): All of the battery level machinery should be in |
| // the same location, and the ifdefs should be contained to the |
| // `BatteryLevelProvider` and SamplingEventSource` instantiation functions. |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| battery_state_sampler_ = std::make_unique<base::BatteryStateSampler>( |
| std::make_unique< |
| performance_manager::power::DbusPowerManagerSamplingEventSource>( |
| chromeos::PowerManagerClient::Get()), |
| std::make_unique< |
| performance_manager::power::BatteryLevelProviderChromeOS>( |
| chromeos::PowerManagerClient::Get())); |
| #elif BUILDFLAG(HAS_BATTERY_LEVEL_PROVIDER_IMPL) |
| battery_state_sampler_ = std::make_unique<base::BatteryStateSampler>(); |
| #endif |
| } |
| } |
| |
| void ChromeBrowserMainExtraPartsPerformanceManager::PreMainMessageLoopRun() { |
| #if !BUILDFLAG(IS_ANDROID) |
| // This object requires the host frame sink manager to exist, which is |
| // created after all the extra parts have run their PostCreateThreads. |
| performance_manager::user_tuning::UserPerformanceTuningManager::GetInstance() |
| ->Start(); |
| |
| // This object is created by the metrics service before threads, but it |
| // needs the UserPerformanceTuningManager to exist. At this point it's |
| // instantiated, but still needs to be initialized. |
| performance_manager::MetricsProviderDesktop::GetInstance()->Initialize(); |
| #endif |
| } |
| |
| void ChromeBrowserMainExtraPartsPerformanceManager::PostMainMessageLoopRun() { |
| // Release all graph nodes before destroying the performance manager. |
| // First release the browser and GPU process nodes. |
| browser_child_process_watcher_->TearDown(); |
| browser_child_process_watcher_.reset(); |
| |
| g_browser_process->profile_manager()->RemoveObserver(this); |
| profile_observations_.RemoveAllObservations(); |
| |
| #if BUILDFLAG(ENABLE_EXTENSIONS) |
| extension_watcher_.reset(); |
| #endif |
| page_load_tracker_decorator_helper_.reset(); |
| page_live_state_data_helper_.reset(); |
| page_load_metrics_observer_.reset(); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| user_performance_tuning_manager_.reset(); |
| profile_discard_opt_out_list_helper_.reset(); |
| |
| if (battery_state_sampler_) |
| battery_state_sampler_->Shutdown(); |
| #endif |
| |
| // Releasing `performance_manager_lifetime_` will tear down the registry and |
| // graph safely. |
| performance_manager_lifetime_.reset(); |
| } |
| |
| void ChromeBrowserMainExtraPartsPerformanceManager::OnProfileAdded( |
| Profile* profile) { |
| profile_observations_.AddObservation(profile); |
| performance_manager::PerformanceManagerRegistry::GetInstance() |
| ->NotifyBrowserContextAdded(profile); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| profile_discard_opt_out_list_helper_->OnProfileAdded(profile); |
| #endif |
| } |
| |
| void ChromeBrowserMainExtraPartsPerformanceManager:: |
| OnOffTheRecordProfileCreated(Profile* off_the_record) { |
| OnProfileAdded(off_the_record); |
| } |
| |
| void ChromeBrowserMainExtraPartsPerformanceManager::OnProfileWillBeDestroyed( |
| Profile* profile) { |
| profile_observations_.RemoveObservation(profile); |
| performance_manager::PerformanceManagerRegistry::GetInstance() |
| ->NotifyBrowserContextRemoved(profile); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| profile_discard_opt_out_list_helper_->OnProfileWillBeRemoved(profile); |
| #endif |
| } |