summaryrefslogtreecommitdiffstats
path: root/src/common/PriorityCache.h
blob: 8233d0ecf27966bd62dc6ea783674bddba7e9790 (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2018 Red Hat
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#ifndef CEPH_PRIORITY_CACHE_H
#define CEPH_PRIORITY_CACHE_H

#include <stdint.h>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include "common/perf_counters.h"
#include "include/ceph_assert.h"

namespace PriorityCache {
  // Reserve 16384 slots for PriorityCache perf counters
  const int PERF_COUNTER_LOWER_BOUND = 1073741824;
  const int PERF_COUNTER_MAX_BOUND = 1073758208;

  enum MallocStats {
    M_FIRST = PERF_COUNTER_LOWER_BOUND,
    M_TARGET_BYTES,
    M_MAPPED_BYTES,
    M_UNMAPPED_BYTES,
    M_HEAP_BYTES,
    M_CACHE_BYTES,
    M_LAST,
  };

  enum Priority {
    PRI0,
    PRI1,
    PRI2,
    PRI3,
    PRI4,
    PRI5,
    PRI6,
    PRI7,
    PRI8,
    PRI9,
    PRI10,
    PRI11,
    LAST = PRI11,
  };

  enum Extra {
    E_RESERVED = Priority::LAST+1,
    E_COMMITTED,
    E_LAST = E_COMMITTED,
  };

  int64_t get_chunk(uint64_t usage, uint64_t total_bytes);

  struct PriCache {
    virtual ~PriCache();

    /* Ask the cache to request memory for the given priority. Note that the
     * cache may ultimately be allocated less memory than it requests here.
     */
    virtual int64_t request_cache_bytes(PriorityCache::Priority pri, uint64_t total_cache) const = 0;

    // Get the number of bytes currently allocated to the given priority.
    virtual int64_t get_cache_bytes(PriorityCache::Priority pri) const = 0;

    // Get the number of bytes currently allocated to all priorities.
    virtual int64_t get_cache_bytes() const = 0;

    // Allocate bytes for a given priority.
    virtual void set_cache_bytes(PriorityCache::Priority pri, int64_t bytes) = 0;

    // Allocate additional bytes for a given priority.
    virtual void add_cache_bytes(PriorityCache::Priority pri, int64_t bytes) = 0;

    /* Commit the current number of bytes allocated to the cache.  Space is
     * allocated in chunks based on the allocation size and current total size
     * of memory available for caches. */
    virtual int64_t commit_cache_size(uint64_t total_cache) = 0;

    /* Get the current number of bytes allocated to the cache. this may be
     * larger than the value returned by get_cache_bytes as it includes extra
     * space for future growth. */
    virtual int64_t get_committed_size() const = 0;

    // Get the ratio of available memory this cache should target.
    virtual double get_cache_ratio() const = 0;

    // Set the ratio of available memory this cache should target.
    virtual void set_cache_ratio(double ratio) = 0;

    // Get the name of this cache.
    virtual std::string get_cache_name() const = 0;

    // Rotate the bins
    virtual void shift_bins() = 0;

    // Import user bins (from PRI1 to LAST-1)
    virtual void import_bins(const std::vector<uint64_t> &bins) = 0;

    // Set bins (PRI0 and LAST should be ignored)
    virtual void set_bins(PriorityCache::Priority pri, uint64_t end_bin) = 0;

    // Get bins
    virtual uint64_t get_bins(PriorityCache::Priority pri) const = 0;
  };

  class Manager {
    CephContext* cct = nullptr;
    PerfCounters* logger;
    std::unordered_map<std::string, PerfCounters*> loggers;
    std::unordered_map<std::string, std::vector<int>> indexes;
    std::unordered_map<std::string, std::shared_ptr<PriCache>> caches;

    // Start perf counter slots after the malloc stats.
    int cur_index = MallocStats::M_LAST;

    uint64_t min_mem = 0;
    uint64_t max_mem = 0;
    uint64_t target_mem = 0;
    uint64_t tuned_mem = 0;
    bool reserve_extra;
    std::string name;
  public:
    Manager(CephContext *c, uint64_t min, uint64_t max, uint64_t target,
            bool reserve_extra, const std::string& name = std::string());
    ~Manager();
    void set_min_memory(uint64_t min) {
      min_mem = min;
    }
    void set_max_memory(uint64_t max) {
      max_mem = max;
    }
    void set_target_memory(uint64_t target) {
      target_mem = target;
    }
    uint64_t get_tuned_mem() const {
      return tuned_mem;
    }
    void insert(const std::string& name, const std::shared_ptr<PriCache> c,
                bool enable_perf_counters);
    void erase(const std::string& name);
    void clear();
    void tune_memory();
    void balance();
    void shift_bins();
  private:
    void balance_priority(int64_t *mem_avail, Priority pri);
  };
}

#endif