File: urgent_page_discarding_policy.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (136 lines) | stat: -rw-r--r-- 5,268 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// 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.

#include "chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h"

#include <memory>

#include "base/feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
#include "chrome/browser/performance_manager/policies/policy_features.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "base/metrics/histogram_macros.h"
#include "chromeos/ash/components/memory/pressure/system_memory_pressure_evaluator.h"
#endif

namespace performance_manager::policies {

namespace {

bool g_disabled_for_testing = false;

#if BUILDFLAG(IS_CHROMEOS)
std::optional<memory_pressure::ReclaimTarget> GetReclaimTarget() {
  std::optional<memory_pressure::ReclaimTarget> reclaim_target = std::nullopt;
  auto* evaluator = ash::memory::SystemMemoryPressureEvaluator::Get();
  if (evaluator) {
    reclaim_target = evaluator->GetCachedReclaimTarget();
  }
  return reclaim_target;
}
#endif  // BUILDFLAG(IS_CHROMEOS)

}  // namespace

UrgentPageDiscardingPolicy::UrgentPageDiscardingPolicy() = default;
UrgentPageDiscardingPolicy::~UrgentPageDiscardingPolicy() = default;

void UrgentPageDiscardingPolicy::OnPassedToGraph(Graph* graph) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!handling_memory_pressure_notification_);
  graph->AddSystemNodeObserver(this);
  DCHECK(PageDiscardingHelper::GetFromGraph(graph))
      << "A PageDiscardingHelper instance should be registered against the "
         "graph in order to use this policy.";
}

void UrgentPageDiscardingPolicy::OnTakenFromGraph(Graph* graph) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  graph->RemoveSystemNodeObserver(this);
}

#if BUILDFLAG(IS_CHROMEOS)
void UrgentPageDiscardingPolicy::OnReclaimTarget(
    base::TimeTicks on_memory_pressure_at,
    std::optional<memory_pressure::ReclaimTarget> reclaim_target) {
  bool discard_protected_pages = true;
  std::optional<base::TimeTicks> origin_time = std::nullopt;
  if (reclaim_target) {
    discard_protected_pages = reclaim_target->discard_protected;
    origin_time = reclaim_target->origin_time;
  }
  std::optional<base::TimeTicks> first_discarded_at =
      PageDiscardingHelper::GetFromGraph(GetOwningGraph())
          ->DiscardMultiplePages(
              reclaim_target, discard_protected_pages,
              DiscardEligibilityPolicy::DiscardReason::URGENT);

  DCHECK(handling_memory_pressure_notification_);
  handling_memory_pressure_notification_ = false;
  if (origin_time && first_discarded_at) {
    base::TimeDelta reclaim_arrival_duration =
        on_memory_pressure_at - *origin_time;
    DEPRECATED_UMA_HISTOGRAM_MEDIUM_TIMES("Discarding.ReclaimArrivalLatency",
                                          reclaim_arrival_duration);
    base::TimeDelta discard_duration =
        *first_discarded_at - on_memory_pressure_at;
    DEPRECATED_UMA_HISTOGRAM_MEDIUM_TIMES("Discarding.DiscardLatency",
                                          discard_duration);
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS)

void UrgentPageDiscardingPolicy::DisableForTesting() {
  g_disabled_for_testing = true;
}

void UrgentPageDiscardingPolicy::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel new_level) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (g_disabled_for_testing) {
    return;
  }

  // The Memory Pressure Monitor will send notifications at regular interval,
  // |handling_memory_pressure_notification_| prevents this class from trying to
  // reply to multiple notifications at the same time.
  if (handling_memory_pressure_notification_ ||
      new_level != base::MemoryPressureListener::MemoryPressureLevel::
                       MEMORY_PRESSURE_LEVEL_CRITICAL) {
    return;
  }

  // Don't discard a page if urgent discarding is disabled. The feature state is
  // checked here instead of at policy creation time so that only clients that
  // experience memory pressure are enrolled in the experiment.
  if (!base::FeatureList::IsEnabled(
          performance_manager::features::kUrgentPageDiscarding)) {
    return;
  }

  handling_memory_pressure_notification_ = true;

#if BUILDFLAG(IS_CHROMEOS)
  base::TimeTicks on_memory_pressure_at = base::TimeTicks::Now();
  // Chrome OS memory pressure evaluator provides the memory reclaim target to
  // leave critical memory pressure. When Chrome OS is under heavy memory
  // pressure, discards multiple tabs to meet the memory reclaim target.
  content::GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
      FROM_HERE, base::BindOnce(GetReclaimTarget),
      base::BindOnce(&UrgentPageDiscardingPolicy::OnReclaimTarget,
                     base::Unretained(this), on_memory_pressure_at));
#else
  PageDiscardingHelper::GetFromGraph(GetOwningGraph())
      ->DiscardAPage(DiscardEligibilityPolicy::DiscardReason::URGENT);
  DCHECK(handling_memory_pressure_notification_);
  handling_memory_pressure_notification_ = false;
#endif  // BUILDFLAG(IS_CHROMEOS)
}

}  // namespace performance_manager::policies