| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_PROFILING_HOST_PROFILING_PROCESS_HOST_H_ |
| #define CHROME_BROWSER_PROFILING_HOST_PROFILING_PROCESS_HOST_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/feature_list.h" |
| #include "base/macros.h" |
| #include "base/memory/singleton.h" |
| #include "base/process/process.h" |
| #include "base/trace_event/memory_dump_provider.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/profiling_host/background_profiling_triggers.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/common/profiling/profiling_client.h" |
| #include "chrome/common/profiling/profiling_client.mojom.h" |
| #include "chrome/common/profiling/profiling_service.mojom.h" |
| #include "content/public/browser/browser_child_process_observer.h" |
| #include "content/public/browser/child_process_data.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| #include "services/service_manager/public/cpp/connector.h" |
| |
| namespace base { |
| class FilePath; |
| } // namespace base |
| |
| namespace content { |
| class RenderProcessHost; |
| } // namespace content |
| |
| namespace profiling { |
| |
| extern const base::Feature kOOPHeapProfilingFeature; |
| extern const char kOOPHeapProfilingFeatureMode[]; |
| |
| // Represents the browser side of the profiling process (//chrome/profiling). |
| // |
| // The profiling process is a singleton. The profiling process infrastructure |
| // is implemented in the Chrome layer so doesn't depend on the content |
| // infrastructure for managing child processes. |
| // |
| // Not thread safe. Should be used on the browser UI thread only. |
| // |
| // The profiling process host can be started normally while Chrome is running, |
| // but can also start in a partial mode where the memory logging connections |
| // are active but the Mojo control channel has not yet been connected. This is |
| // to support starting the profiling process very early in the startup |
| // process (to get most memory events) before other infrastructure like the |
| // I/O thread has been started. |
| // |
| // TODO(ajwong): This host class seems over kill at this point. Can this be |
| // fully subsumed by the ProfilingService class? |
| class ProfilingProcessHost : public content::BrowserChildProcessObserver, |
| content::NotificationObserver, |
| base::trace_event::MemoryDumpProvider { |
| public: |
| // These values are persisted to logs. Entries should not be renumbered and |
| // numeric values should never be reused. |
| enum class Mode { |
| // No profiling enabled. |
| kNone = 0, |
| |
| // Only profile the browser and GPU processes. |
| kMinimal = 1, |
| |
| // Profile all processes. |
| kAll = 2, |
| |
| // Profile only the browser process. |
| kBrowser = 3, |
| |
| // Profile only the gpu process. |
| kGpu = 4, |
| |
| // Profile a sampled number of renderer processes. |
| kRendererSampling = 5, |
| |
| kCount |
| }; |
| |
| // Returns the mode. |
| Mode mode() const { return mode_; } |
| |
| // Returns the mode set on the current process' command line. |
| static Mode GetCurrentMode(); |
| static Mode ConvertStringToMode(const std::string& input); |
| bool ShouldProfileProcessType(int process_type); |
| |
| // Launches the profiling process and returns a pointer to it. |
| static ProfilingProcessHost* Start( |
| content::ServiceManagerConnection* connection, |
| Mode mode); |
| |
| // Returns true if Start() has been called. |
| static bool has_started() { return has_started_; } |
| |
| // Returns a pointer to the current global profiling process host. |
| static ProfilingProcessHost* GetInstance(); |
| |
| void ConfigureBackgroundProfilingTriggers(); |
| |
| // Create a trace with a heap dump at the given path. |
| // This is equivalent to navigating to chrome://tracing, taking a trace with |
| // only the memory-infra category selected, waiting 10 seconds, and saving the |
| // result to |dest|. |
| // |done| will be called on the UI thread. |
| using SaveTraceFinishedCallback = base::OnceCallback<void(bool success)>; |
| void SaveTraceWithHeapDumpToFile( |
| base::FilePath dest, |
| SaveTraceFinishedCallback done, |
| bool stop_immediately_after_heap_dump_for_tests); |
| |
| // Sends a message to the profiling process to report all profiled processes |
| // memory data to the crash server (slow-report). |
| void RequestProcessReport(std::string trigger_name); |
| |
| using TraceFinishedCallback = |
| base::OnceCallback<void(bool success, std::string trace_json)>; |
| |
| // This method must be called from the UI thread. |callback| will be called |
| // asynchronously on the UI thread. If |
| // |stop_immediately_after_heap_dump_for_tests| is true, then |callback| will |
| // be called as soon as the heap dump is added to the trace. Otherwise, |
| // |callback| will be called after 10s. This gives time for the |
| // MemoryDumpProviders to dump to the trace, which is asynchronous and has no |
| // finish notification. This intentionally avoids waiting for the heap-dump |
| // finished signal, in case there's a problem with the profiling process and |
| // the heap-dump is never added to the trace. |
| // Public for testing. |
| void RequestTraceWithHeapDump( |
| TraceFinishedCallback callback, |
| bool stop_immediately_after_heap_dump_for_tests); |
| |
| private: |
| friend struct base::DefaultSingletonTraits<ProfilingProcessHost>; |
| friend class BackgroundProfilingTriggersTest; |
| friend class MemlogBrowserTest; |
| friend class ProfilingTestDriver; |
| FRIEND_TEST_ALL_PREFIXES(ProfilingProcessHost, ShouldProfileNewRenderer); |
| |
| ProfilingProcessHost(); |
| ~ProfilingProcessHost() override; |
| |
| void Register(); |
| void Unregister(); |
| |
| // Set the profiling mode. Exposed for unittests. |
| void SetMode(Mode mode); |
| |
| // Make and store a connector from |connection|. |
| void MakeConnector(content::ServiceManagerConnection* connection); |
| |
| // BrowserChildProcessObserver |
| // Observe connection of non-renderer child processes. |
| void BrowserChildProcessLaunchedAndConnected( |
| const content::ChildProcessData& data) override; |
| |
| // NotificationObserver |
| // Observe connection of renderer child processes. |
| void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) override; |
| |
| // base::trace_event::MemoryDumpProvider |
| bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, |
| base::trace_event::ProcessMemoryDump* pmd) override; |
| |
| void OnDumpProcessesForTracingCallback( |
| uint64_t guid, |
| std::vector<profiling::mojom::SharedBufferWithSizePtr> buffers); |
| |
| // Starts the profiling process. |
| void LaunchAsService(); |
| |
| // Called on the UI thread after the heap dump has been added to the trace. |
| void DumpProcessFinishedUIThread(); |
| |
| // Sends the end of the data pipe to the profiling service. |
| void AddClientToProfilingService(profiling::mojom::ProfilingClientPtr client, |
| base::ProcessId pid, |
| profiling::mojom::ProcessType process_type); |
| |
| void SaveTraceToFileOnBlockingThread(base::FilePath dest, |
| std::string trace, |
| SaveTraceFinishedCallback done); |
| |
| // Reports the profiling mode. |
| void ReportMetrics(); |
| |
| // Helpers for controlling process selection for the sampling modes. |
| bool ShouldProfileNewRenderer(content::RenderProcessHost* renderer) const; |
| |
| // Sets up the profiling connection for the given child process. |
| void StartProfilingNonRendererChild( |
| int child_process_id, |
| base::ProcessId proc_id, |
| profiling::mojom::ProcessType process_type); |
| |
| // SetRenderer. |
| void SetRendererSamplingAlwaysProfileForTest(); |
| |
| content::NotificationRegistrar registrar_; |
| std::unique_ptr<service_manager::Connector> connector_; |
| mojom::ProfilingServicePtr profiling_service_; |
| |
| // Whether or not the host is registered to the |registrar_|. |
| bool is_registered_; |
| |
| // Handle background triggers on high memory pressure. A trigger will call |
| // |RequestProcessReport| on this instance. |
| BackgroundProfilingTriggers background_triggers_; |
| |
| // Every 24-hours, reports the profiling mode. |
| base::RepeatingTimer metrics_timer_; |
| |
| // The mode determines which processes should be profiled. |
| Mode mode_; |
| |
| // Whether or not the profiling host is started. |
| static bool has_started_; |
| |
| // If in kRendererSampling mode, this is used to identify the currently |
| // profiled renderer. If no renderer is being profiled, this is set to |
| // nullptr. This variable shouild only be accessed on the UI thread and |
| // the value should be considered opaque. |
| // |
| // Semantically, the value must be something that identifies which |
| // specific RenderProcess is being profiled. When the underlying RenderProcess |
| // goes away, this value needs to be reset to nullptr. The RenderProcessHost |
| // pointer and the NOTIFICATION_RENDERER_PROCESS_CREATED notification can be |
| // used to provide these semantics. |
| void* profiled_renderer_; |
| |
| // For Tests. In kRendererSampling mode, overrides sampling to always profile |
| // a renderer process if one is already not going. |
| bool always_sample_for_tests_; |
| |
| // Only used for testing. Must only ever be used from the UI thread. Will be |
| // called after the profiling process dumps heaps into the trace log. |
| base::OnceClosure dump_process_for_tracing_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ProfilingProcessHost); |
| }; |
| |
| } // namespace profiling |
| |
| #endif // CHROME_BROWSER_PROFILING_HOST_PROFILING_PROCESS_HOST_H_ |