v8_detailed_memory_any_seq.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.h"
  5. #include <memory>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/memory/weak_ptr.h"
  10. #include "base/observer_list.h"
  11. #include "base/threading/sequenced_task_runner_handle.h"
  12. #include "components/performance_manager/public/graph/frame_node.h"
  13. #include "components/performance_manager/public/graph/graph.h"
  14. #include "components/performance_manager/public/graph/process_node.h"
  15. #include "components/performance_manager/public/performance_manager.h"
  16. #include "components/performance_manager/public/render_frame_host_proxy.h"
  17. #include "content/public/browser/browser_task_traits.h"
  18. #include "content/public/browser/browser_thread.h"
  19. namespace performance_manager {
  20. namespace v8_memory {
  21. ////////////////////////////////////////////////////////////////////////////////
  22. // V8DetailedMemoryRequestAnySeq
  23. V8DetailedMemoryRequestAnySeq::V8DetailedMemoryRequestAnySeq(
  24. const base::TimeDelta& min_time_between_requests,
  25. MeasurementMode mode,
  26. absl::optional<RenderProcessHostId> process_to_measure) {
  27. absl::optional<base::WeakPtr<ProcessNode>> process_node;
  28. if (process_to_measure) {
  29. // GetProcessNodeForRenderProcessHostId must be called from the UI thread.
  30. auto ui_task_runner = content::GetUIThreadTaskRunner({});
  31. if (!ui_task_runner->RunsTasksInCurrentSequence()) {
  32. ui_task_runner->PostTaskAndReplyWithResult(
  33. FROM_HERE,
  34. base::BindOnce(
  35. &PerformanceManager::GetProcessNodeForRenderProcessHostId,
  36. process_to_measure.value()),
  37. base::BindOnce(
  38. &V8DetailedMemoryRequestAnySeq::InitializeWrappedRequest,
  39. weak_factory_.GetWeakPtr(), min_time_between_requests, mode));
  40. return;
  41. }
  42. process_node = PerformanceManager::GetProcessNodeForRenderProcessHostId(
  43. process_to_measure.value());
  44. }
  45. InitializeWrappedRequest(min_time_between_requests, mode,
  46. std::move(process_node));
  47. }
  48. V8DetailedMemoryRequestAnySeq::~V8DetailedMemoryRequestAnySeq() {
  49. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  50. PerformanceManager::CallOnGraph(
  51. FROM_HERE, base::BindOnce(
  52. [](std::unique_ptr<V8DetailedMemoryRequest> request) {
  53. request.reset();
  54. },
  55. std::move(request_)));
  56. }
  57. bool V8DetailedMemoryRequestAnySeq::HasObserver(
  58. V8DetailedMemoryObserverAnySeq* observer) {
  59. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  60. return observers_.HasObserver(observer);
  61. }
  62. void V8DetailedMemoryRequestAnySeq::AddObserver(
  63. V8DetailedMemoryObserverAnySeq* observer) {
  64. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  65. observers_.AddObserver(observer);
  66. }
  67. void V8DetailedMemoryRequestAnySeq::RemoveObserver(
  68. V8DetailedMemoryObserverAnySeq* observer) {
  69. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  70. DCHECK(observers_.HasObserver(observer));
  71. observers_.RemoveObserver(observer);
  72. }
  73. void V8DetailedMemoryRequestAnySeq::NotifyObserversOnMeasurementAvailable(
  74. base::PassKey<V8DetailedMemoryRequest>,
  75. RenderProcessHostId render_process_host_id,
  76. const V8DetailedMemoryProcessData& process_data,
  77. const V8DetailedMemoryObserverAnySeq::FrameDataMap& frame_data) const {
  78. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  79. for (V8DetailedMemoryObserverAnySeq& observer : observers_)
  80. observer.OnV8MemoryMeasurementAvailable(render_process_host_id,
  81. process_data, frame_data);
  82. }
  83. void V8DetailedMemoryRequestAnySeq::InitializeWrappedRequest(
  84. const base::TimeDelta& min_time_between_requests,
  85. MeasurementMode mode,
  86. absl::optional<base::WeakPtr<ProcessNode>> process_to_measure) {
  87. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  88. // After construction the V8DetailedMemoryRequest must only be accessed on
  89. // the graph sequence.
  90. request_ = std::make_unique<V8DetailedMemoryRequest>(
  91. base::PassKey<V8DetailedMemoryRequestAnySeq>(), min_time_between_requests,
  92. mode, std::move(process_to_measure), weak_factory_.GetWeakPtr());
  93. }
  94. ////////////////////////////////////////////////////////////////////////////////
  95. // V8DetailedMemoryRequestOneShotAnySeq
  96. V8DetailedMemoryRequestOneShotAnySeq::V8DetailedMemoryRequestOneShotAnySeq(
  97. MeasurementMode mode)
  98. : mode_(mode) {}
  99. V8DetailedMemoryRequestOneShotAnySeq::V8DetailedMemoryRequestOneShotAnySeq(
  100. RenderProcessHostId process_id,
  101. MeasurementCallback callback,
  102. MeasurementMode mode)
  103. : mode_(mode) {
  104. StartMeasurement(process_id, std::move(callback));
  105. }
  106. V8DetailedMemoryRequestOneShotAnySeq::~V8DetailedMemoryRequestOneShotAnySeq() {
  107. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  108. PerformanceManager::CallOnGraph(
  109. FROM_HERE,
  110. base::BindOnce(
  111. [](std::unique_ptr<V8DetailedMemoryRequestOneShot> request) {
  112. request.reset();
  113. },
  114. std::move(request_)));
  115. }
  116. void V8DetailedMemoryRequestOneShotAnySeq::StartMeasurement(
  117. RenderProcessHostId process_id,
  118. MeasurementCallback callback) {
  119. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  120. // GetProcessNodeForRenderProcessHostId must be called from the UI thread.
  121. auto ui_task_runner = content::GetUIThreadTaskRunner({});
  122. if (ui_task_runner->RunsTasksInCurrentSequence()) {
  123. InitializeWrappedRequest(
  124. std::move(callback), mode_,
  125. PerformanceManager::GetProcessNodeForRenderProcessHostId(process_id));
  126. } else {
  127. ui_task_runner->PostTaskAndReplyWithResult(
  128. FROM_HERE,
  129. base::BindOnce(
  130. &PerformanceManager::GetProcessNodeForRenderProcessHostId,
  131. process_id),
  132. base::BindOnce(
  133. &V8DetailedMemoryRequestOneShotAnySeq::InitializeWrappedRequest,
  134. weak_factory_.GetWeakPtr(), std::move(callback), mode_));
  135. }
  136. }
  137. void V8DetailedMemoryRequestOneShotAnySeq::InitializeWrappedRequest(
  138. MeasurementCallback callback,
  139. MeasurementMode mode,
  140. base::WeakPtr<ProcessNode> process_node) {
  141. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  142. // Pass ownership of |callback| to a wrapper, |wrapped_callback|, that will
  143. // be owned by the wrapped request. The wrapper will be invoked and destroyed
  144. // on the PM sequence. However, |callback| must be both called and destroyed
  145. // on this sequence, so indirect all accesses to it through SequenceBound.
  146. auto wrapped_callback = base::BindOnce(
  147. &V8DetailedMemoryRequestOneShotAnySeq::OnMeasurementAvailable,
  148. base::SequenceBound<MeasurementCallback>(
  149. base::SequencedTaskRunnerHandle::Get(), std::move(callback)));
  150. // After construction the V8DetailedMemoryRequest must only be accessed on
  151. // the graph sequence.
  152. request_ = std::make_unique<V8DetailedMemoryRequestOneShot>(
  153. base::PassKey<V8DetailedMemoryRequestOneShotAnySeq>(),
  154. std::move(process_node), std::move(wrapped_callback), mode);
  155. }
  156. // static
  157. void V8DetailedMemoryRequestOneShotAnySeq::OnMeasurementAvailable(
  158. base::SequenceBound<MeasurementCallback> sequence_bound_callback,
  159. const ProcessNode* process_node,
  160. const V8DetailedMemoryProcessData* process_data) {
  161. DCHECK(process_node);
  162. DCHECK_ON_GRAPH_SEQUENCE(process_node->GetGraph());
  163. using FrameAndData = std::pair<content::GlobalRenderFrameHostId,
  164. V8DetailedMemoryExecutionContextData>;
  165. std::vector<FrameAndData> all_frame_data;
  166. process_node->VisitFrameNodes(base::BindRepeating(
  167. [](std::vector<FrameAndData>* all_frame_data,
  168. const FrameNode* frame_node) {
  169. const auto* frame_data =
  170. V8DetailedMemoryExecutionContextData::ForFrameNode(frame_node);
  171. if (frame_data) {
  172. all_frame_data->push_back(std::make_pair(
  173. frame_node->GetRenderFrameHostProxy().global_frame_routing_id(),
  174. *frame_data));
  175. }
  176. return true;
  177. },
  178. base::Unretained(&all_frame_data)));
  179. sequence_bound_callback.PostTaskWithThisObject(
  180. base::BindOnce(
  181. [](RenderProcessHostId process_id,
  182. const V8DetailedMemoryProcessData& process_data,
  183. const FrameDataMap& frame_data, MeasurementCallback* callback) {
  184. std::move(*callback).Run(process_id, process_data, frame_data);
  185. },
  186. process_node->GetRenderProcessHostId(), *process_data,
  187. std::move(all_frame_data)));
  188. }
  189. } // namespace v8_memory
  190. } // namespace performance_manager