chromium/components/performance_manager/public/v8_memory/v8_detailed_memory.h

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_V8_DETAILED_MEMORY_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_V8_DETAILED_MEMORY_H_

#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"

namespace performance_manager {

namespace execution_context {
class ExecutionContext;
}  // namespace execution_context

class Graph;
class FrameNode;
class ProcessNode;
class WorkerNode;

namespace v8_memory {

// Classes that query each renderer process for the amount of memory used by V8
// in each frame.
//
// To start sampling create a V8DetailedMemoryRequest object that specifies how
// often to request a memory measurement. Delete the object when you no longer
// need measurements. Measurement involves some overhead so choose the lowest
// sampling frequency your use case needs. Performance Manager will use the
// highest sampling frequency that any caller requests, and stop measurements
// entirely when no more request objects exist.
//
// When measurements are available Performance Manager attaches them to
// V8DetailedMemoryExecutionContextData and V8DetailedMemoryProcessData objects
// that can be retrieved with V8DetailedMemoryExecutionContextData's
// ForFrameNode, ForWorkerNode and ForExecutionContext, and
// V8DetailedMemoryProcessData's ForProcessNode.  V8DetailedMemoryProcessData
// objects can be cleaned up when V8DetailedMemoryRequest objects are deleted
// so callers must save the measurements they are interested in before
// releasing their V8DetailedMemoryRequest.
//
// Callers can be notified when a request is available by implementing
// V8DetailedMemoryObserver.
//
// V8DetailedMemoryRequest, V8DetailedMemoryExecutionContextData and
// V8DetailedMemoryProcessData must all be accessed on the graph sequence, and
// V8DetailedMemoryObserver::OnV8MemoryMeasurementAvailable will be called on
// this sequence. To request memory measurements from another sequence use the
// wrappers in v8_detailed_memory_any_seq.h.
//
// Usage:
//
// Take a memory measurement every 30 seconds and register an observer for the
// results:
//
//   class Observer : public V8DetailedMemoryObserver {
//    public:
//     // Called on the PM sequence for each process.
//     void OnV8MemoryMeasurementAvailable(
//         const ProcessNode* process_node,
//         const V8DetailedMemoryProcessData* data) override {
//       DCHECK(data);
//       LOG(INFO) << "Process " << process_node->GetProcessId() <<
//           " reported " << data->detached_v8_bytes_used() <<
//           " bytes of V8 memory that wasn't associated with a frame.";
//       LOG(INFO) << "Process " << process_node->GetProcessId() <<
//           " reported " << data->shared_v8_bytes_used() <<
//           " bytes of V8 memory that are shared between all frames";
//       for (auto* frame_node : process_node->GetFrameNodes()) {
//         auto* frame_data =
//             V8DetailedMemoryExecutionContextData::ForFrame(frame_node);
//         if (frame_data) {
//           LOG(INFO) << "Frame " << frame_node->GetFrameToken().value() <<
//               " reported " << frame_data->v8_bytes_used() <<
//               " bytes of V8 memory in its main world.";
//         }
//       }
//      }
//   };
//
//   class MemoryMonitor {
//    public:
//     MemoryMonitor() {
//       PerformanceManager::CallOnGraph(FROM_HERE,
//           base::BindOnce(&Start, base::Unretained(this)));
//     }
//
//     void Start(Graph* graph) {
//       DCHECK_ON_GRAPH_SEQUENCE(graph);
//
//       // Creating a V8DetailedMemoryRequest with the |graph| parameter
//       // automatically starts measurements.
//       request_ = std::make_unique<V8DetailedMemoryRequest>(
//           base::Seconds(30), graph);
//       observer_ = std::make_unique<Observer>();
//       request_->AddObserver(observer_.get());
//     }
//
//     void Stop(Graph* graph) {
//       DCHECK_ON_GRAPH_SEQUENCE(graph);
//
//       // |observer_| must be removed from |request_| before deleting it.
//       // Afterwards they can be deleted in any order.
//       request_->RemoveObserver(observer_.get());
//       observer_.reset();
//
//       // Measurements stop when |request_| is deleted.
//       request_.reset();
//     }
//
//    private:
//     std::unique_ptr<V8DetailedMemoryRequest> request_;
//     std::unique_ptr<Observer> observer_;
//   };

//////////////////////////////////////////////////////////////////////////////
// The following classes report results from memory measurements.

class V8DetailedMemoryExecutionContextData {};

class V8DetailedMemoryProcessData {};

class V8DetailedMemoryObserver : public base::CheckedObserver {};

//////////////////////////////////////////////////////////////////////////////
// The following classes create requests for memory measurements.

class V8DetailedMemoryDecorator;
class V8DetailedMemoryRequestAnySeq;
class V8DetailedMemoryRequestOneShot;
class V8DetailedMemoryRequestQueue;

class V8DetailedMemoryRequest {};

class V8DetailedMemoryRequestOneShotAnySeq;

class V8DetailedMemoryRequestOneShot final : public V8DetailedMemoryObserver {};

//////////////////////////////////////////////////////////////////////////////
// The following internal functions are exposed in the header for testing.

namespace internal {

// Enables or disables MeasurementMode::kEagerModeForTesting. Creating eager
// measurement requests can have a high performance penalty so this should only
// be enabled in tests.
void SetEagerMemoryMeasurementEnabledForTesting(bool enable);

}  // namespace internal

}  // namespace v8_memory

}  // namespace performance_manager

#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_V8_DETAILED_MEMORY_H_