chromium/chrome/browser/performance_manager/policies/oom_score_policy_chromeos.h

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

#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_OOM_SCORE_POLICY_CHROMEOS_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_OOM_SCORE_POLICY_CHROMEOS_H_

#include <vector>

#include "base/containers/flat_map.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/page_node.h"

namespace performance_manager::policies {

// Assigning oom score adj to renderer processes. Process with lowest oom score
// adj is the last to be killed by Linux oom killer. The more important process
// would be assigned lower oom score adj. See the following web page for more
// explanation on Linux oom score adj(adjust).
// [1]: https://man7.org/linux/man-pages/man1/choom.1.html
class OomScorePolicyChromeOS : public GraphOwned,
                               public PageNode::ObserverDefaultImpl {
 public:
  OomScorePolicyChromeOS();
  ~OomScorePolicyChromeOS() override;
  OomScorePolicyChromeOS(const OomScorePolicyChromeOS& other) = delete;
  OomScorePolicyChromeOS& operator=(const OomScorePolicyChromeOS&) = delete;

  // GraphOwned implementation:
  void OnPassedToGraph(Graph* graph) override;
  void OnTakenFromGraph(Graph* graph) override;

  // PageNode::ObserverDefaultImpl:
  void OnPageNodeAdded(const PageNode* page_node) override;
  void OnBeforePageNodeRemoved(const PageNode* page_node) override;
  void OnIsFocusedChanged(const PageNode* page_node) override;
  void OnIsVisibleChanged(const PageNode* page_node) override;
  void OnTypeChanged(const PageNode* page_node,
                     PageType previous_type) override;

 protected:
  // These members are protected for testing.
  void HandlePageNodeEvents();

  // Returns the cached oom score adj. If the pid is not cached, returns -1 (a
  // value not in the valid oom score adj range for renderer processes).
  int GetCachedOomScore(base::ProcessId pid);

 private:
  // Cache OOM scores in memory.
  using ProcessScoreMap = base::flat_map<base::ProcessId, int>;

  // OomScorePolicyChromeOS is active when receiving page node events.
  void HandlePageNodeEventsThrottled();

  ProcessScoreMap DistributeOomScore(
      const std::vector<PageNodeSortProxy>& candidates);

  // Returns a vector of pids of the main frame renderer process of the
  // |candidates| (the child frame renderer processes are ignored). The order of
  // the pids is corresponding to the order of the |candidates|.
  std::vector<base::ProcessId> GetUniquePids(
      const std::vector<PageNodeSortProxy>& candidates);

  base::TimeTicks last_oom_scores_assignment_ = base::TimeTicks::Now();

  // Map maintaining the process handle - oom_score mapping.
  ProcessScoreMap oom_score_map_;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<OomScorePolicyChromeOS> weak_factory_{this};
};

}  // namespace performance_manager::policies

#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_OOM_SCORE_POLICY_CHROMEOS_H_