// -*- 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 #include #include #include #include #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 &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 loggers; std::unordered_map> indexes; std::unordered_map> 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 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