mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 08:16:09 +03:00
185 lines
7.2 KiB
C++
185 lines
7.2 KiB
C++
// 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 BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_
|
|
#define BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "base/base_export.h"
|
|
#include "base/callback.h"
|
|
#include "base/macros.h"
|
|
#include "base/memory/ref_counted.h"
|
|
|
|
namespace base {
|
|
|
|
class SequencedTaskRunner;
|
|
|
|
namespace trace_event {
|
|
|
|
struct MemoryDumpProviderInfo;
|
|
|
|
// Detects temporally local memory peaks. Peak detection is based on
|
|
// continuously querying memory usage using MemoryDumpprovider(s) that support
|
|
// fast polling (e.g., ProcessMetricsDumpProvider which under the hoods reads
|
|
// /proc/PID/statm on Linux) and using a combination of:
|
|
// - An static threshold (currently 1% of total system memory).
|
|
// - Sliding window stddev analysis.
|
|
// Design doc: https://goo.gl/0kOU4A .
|
|
// This class is NOT thread-safe, the caller has to ensure linearization of
|
|
// the calls to the public methods. In any case, the public methods do NOT have
|
|
// to be called from the |task_runner| on which the polling tasks run.
|
|
class BASE_EXPORT MemoryPeakDetector {
|
|
public:
|
|
using OnPeakDetectedCallback = RepeatingClosure;
|
|
using DumpProvidersList = std::vector<scoped_refptr<MemoryDumpProviderInfo>>;
|
|
using GetDumpProvidersFunction = RepeatingCallback<void(DumpProvidersList*)>;
|
|
|
|
enum State {
|
|
NOT_INITIALIZED = 0, // Before Setup()
|
|
DISABLED, // Before Start() or after Stop().
|
|
ENABLED, // After Start() but no dump_providers_ are available.
|
|
RUNNING // After Start(). The PollMemoryAndDetectPeak() task is scheduled.
|
|
};
|
|
|
|
// Peak detector configuration, passed to Start().
|
|
struct BASE_EXPORT Config {
|
|
Config();
|
|
Config(uint32_t polling_interval_ms,
|
|
uint32_t min_time_between_peaks_ms,
|
|
bool enable_verbose_poll_tracing);
|
|
|
|
// The rate at which memory will be polled. Polls will happen on the task
|
|
// runner passed to Setup().
|
|
uint32_t polling_interval_ms;
|
|
|
|
// Two consecutive peak detection callbacks will happen at least
|
|
// |min_time_between_peaks_ms| apart from each other.
|
|
uint32_t min_time_between_peaks_ms;
|
|
|
|
// When enabled causes a TRACE_COUNTER event to be injected in the trace
|
|
// for each poll (if tracing is enabled).
|
|
bool enable_verbose_poll_tracing;
|
|
};
|
|
|
|
static MemoryPeakDetector* GetInstance();
|
|
|
|
// Configures the peak detector, binding the polling tasks on the given
|
|
// thread. Setup() can be called several times, provided that: (1) Stop()
|
|
// is called; (2a) the previous task_runner is flushed or (2b) the task_runner
|
|
// remains the same.
|
|
// GetDumpProvidersFunction: is the function that will be invoked to get
|
|
// an updated list of polling-capable dump providers. This is really just
|
|
// MemoryDumpManager::GetDumpProvidersForPolling, but this extra level of
|
|
// indirection allows easier testing.
|
|
// SequencedTaskRunner: the task runner where PollMemoryAndDetectPeak() will
|
|
// be periodically called.
|
|
// OnPeakDetectedCallback: a callback that will be invoked on the
|
|
// given task runner when a memory peak is detected.
|
|
void Setup(const GetDumpProvidersFunction&,
|
|
const scoped_refptr<SequencedTaskRunner>&,
|
|
const OnPeakDetectedCallback&);
|
|
|
|
// Releases the |task_runner_| and the bound callbacks.
|
|
void TearDown();
|
|
|
|
// This posts a task onto the passed task runner which refreshes the list of
|
|
// dump providers via the GetDumpProvidersFunction. If at least one dump
|
|
// provider is available, this starts immediately polling on the task runner.
|
|
// If not, the detector remains in the ENABLED state and will start polling
|
|
// automatically (i.e. without requiring another call to Start()) on the
|
|
// next call to NotifyMemoryDumpProvidersChanged().
|
|
void Start(Config);
|
|
|
|
// Stops the polling on the task runner (if was active at all). This doesn't
|
|
// wait for the task runner to drain pending tasks, so it is possible that
|
|
// a polling will happen concurrently (or in the immediate future) with the
|
|
// Stop() call. It is responsibility of the caller to drain or synchronize
|
|
// with the task runner.
|
|
void Stop();
|
|
|
|
// If Start()-ed, prevents that a peak callback is triggered before the next
|
|
// |min_time_between_peaks_ms|. No-op if the peak detector is not enabled.
|
|
void Throttle();
|
|
|
|
// Used by MemoryDumpManager to notify that the list of polling-capable dump
|
|
// providers has changed. The peak detector will reload the list on the next
|
|
// polling task. This function can be called before Setup(), in which
|
|
// case will be just a no-op.
|
|
void NotifyMemoryDumpProvidersChanged();
|
|
|
|
void SetStaticThresholdForTesting(uint64_t static_threshold_bytes);
|
|
|
|
private:
|
|
friend class MemoryPeakDetectorTest;
|
|
|
|
static constexpr uint32_t kSlidingWindowNumSamples = 50;
|
|
|
|
MemoryPeakDetector();
|
|
~MemoryPeakDetector();
|
|
|
|
// All these methods are always called on the |task_runner_|.
|
|
void StartInternal(Config);
|
|
void StopInternal();
|
|
void TearDownInternal();
|
|
void ReloadDumpProvidersAndStartPollingIfNeeded();
|
|
void PollMemoryAndDetectPeak(uint32_t expected_generation);
|
|
bool DetectPeakUsingSlidingWindowStddev(uint64_t last_sample_bytes);
|
|
void ResetPollHistory(bool keep_last_sample = false);
|
|
|
|
// It is safe to call these testing methods only on the |task_runner_|.
|
|
State state_for_testing() const { return state_; }
|
|
uint32_t poll_tasks_count_for_testing() const {
|
|
return poll_tasks_count_for_testing_;
|
|
}
|
|
|
|
// The task runner where all the internal calls are posted onto. This field
|
|
// must be NOT be accessed by the tasks posted on the |task_runner_| because
|
|
// there might still be outstanding tasks on the |task_runner_| while this
|
|
// refptr is reset. This can only be safely accessed by the public methods
|
|
// above, which the client of this class is supposed to call sequentially.
|
|
scoped_refptr<SequencedTaskRunner> task_runner_;
|
|
|
|
// After the Setup() call, the fields below, must be accessed only from
|
|
// the |task_runner_|.
|
|
|
|
// Bound function to get an updated list of polling-capable dump providers.
|
|
GetDumpProvidersFunction get_dump_providers_function_;
|
|
|
|
// The callback to invoke when peaks are detected.
|
|
OnPeakDetectedCallback on_peak_detected_callback_;
|
|
|
|
// List of polling-aware dump providers to invoke upon each poll.
|
|
DumpProvidersList dump_providers_;
|
|
|
|
// The generation is incremented every time the |state_| is changed and causes
|
|
// PollMemoryAndDetectPeak() to early out if the posted task doesn't match the
|
|
// most recent |generation_|. This allows to drop on the floor outstanding
|
|
// PostDelayedTask that refer to an old sequence that was later Stop()-ed or
|
|
// disabled because of NotifyMemoryDumpProvidersChanged().
|
|
uint32_t generation_;
|
|
|
|
State state_;
|
|
|
|
// Config passed to Start(), only valid when |state_| = {ENABLED, RUNNING}.
|
|
Config config_;
|
|
|
|
uint64_t static_threshold_bytes_;
|
|
uint32_t skip_polls_;
|
|
uint64_t last_dump_memory_total_;
|
|
uint64_t samples_bytes_[kSlidingWindowNumSamples];
|
|
uint32_t samples_index_;
|
|
uint32_t poll_tasks_count_for_testing_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MemoryPeakDetector);
|
|
};
|
|
|
|
} // namespace trace_event
|
|
} // namespace base
|
|
|
|
#endif // BASE_TRACE_EVENT_MEMORY_PEAK_DETECTOR_H_
|