chromium/components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.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_ANY_SEQ_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_V8_DETAILED_MEMORY_ANY_SEQ_H_

#include <memory>
#include <optional>

#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/threading/sequence_bound.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
#include "components/performance_manager/public/render_process_host_id.h"
#include "components/performance_manager/public/v8_memory/v8_detailed_memory.h"
#include "content/public/browser/global_routing_id.h"

namespace performance_manager {

class ProcessNode;

namespace v8_memory {

// Classes that work similarly to V8DetailedMemoryRequest and
// V8DetailedMemoryRequestOneShot, but can be called from any sequence.
//
// To start sampling create a V8DetailedMemoryRequestAnySeq 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 each V8DetailedMemoryObserverAnySeq
// object you supply will be invoked with a copy of the results.
//
// Usage:
//
// Take a memory measurement every 30 seconds and register an observer for
// the results:
//
//   class Observer : public V8DetailedMemoryObserverAnySeq {
//    public:
//     // Called on the same sequence for each process.
//     void OnV8MemoryMeasurementAvailable(
//         RenderProcessHostId process_id,
//         const V8DetailedMemoryProcessData& process_data,
//         const V8DetailedMemoryObserverAnySeq::FrameDataMap& frame_data)
//         override {
//       const auto* process = RenderProcessHost::FromID(process_id.value());
//       if (!process) {
//         // Process was deleted after measurement arrived on the PM sequence.
//         return;
//       }
//       LOG(INFO) << "Process " << process->GetID() <<
//           " reported " << process_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 (std::pair<
//             content::GlobalRenderFrameHostId,
//             V8DetailedMemoryExecutionContextData
//           > frame_and_data : frame_data) {
//         const auto* frame = RenderFrameHost::FromID(frame_and_data.first);
//         if (!frame) {
//           // Frame was deleted after measurement arrived on the PM sequence.
//           continue;
//         }
//         LOG(INFO) << "Frame " << frame->GetFrameToken() <<
//             " using " << token_and_data.second.v8_bytes_used() <<
//             " bytes of V8 memory in its main world.";
//       }
//     }
//   };
//
//  class MemoryMonitor {
//    public:
//     MemoryMonitor() {
//       Start();
//     }
//
//     void Start() {
//       DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
//
//       // Creating a V8DetailedMemoryRequest with the |graph| parameter
//       // automatically starts measurements.
//       request_ = std::make_unique<V8DetailedMemoryRequestAnySeq>(
//           base::Minutes(2));
//       observer_ = std::make_unique<Observer>();
//       request_->AddObserver(observer_.get());
//     }
//
//     void Stop() {
//       DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
//
//       // |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<V8DetailedMemoryRequestAnySeq> request_;
//     std::unique_ptr<Observer> observer_;
//
//     SEQUENCE_CHECKER(sequence_checker_);
//   };

// Observer that can be created on any sequence, and will be notified on
// that sequence when measurements are available. Register the observer
// through V8DetailedMemoryRequestAnySeq::AddObserver. The
// V8DetailedMemoryRequestAnySeq must live on the same sequence as the
// observer.
class V8DetailedMemoryObserverAnySeq : public base::CheckedObserver {};

// Wrapper that can instantiate a V8DetailedMemoryRequest from any sequence.
class V8DetailedMemoryRequestAnySeq {};

// Wrapper that can instantiate a V8DetailedMemoryRequestOneShot from any
// sequence.
class V8DetailedMemoryRequestOneShotAnySeq {};

}  // namespace v8_memory

}  // namespace performance_manager

#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_V8_MEMORY_V8_DETAILED_MEMORY_ANY_SEQ_H_