libfoedus-core
FOEDUS Core Library
foedus::cache::CacheManagerPimpl Class Referencefinal

Pimpl object of CacheManager. More...

Detailed Description

Pimpl object of CacheManager.

A private pimpl object for CacheManager. Do not include this header from a client program unless you know what you are doing.

Eviction Policy
So far we use a simple CLOCK algorithm to minimize the overhead, especially synchronization overhead.

Definition at line 44 of file cache_manager_pimpl.hpp.

#include <cache_manager_pimpl.hpp>

Inheritance diagram for foedus::cache::CacheManagerPimpl:
Collaboration diagram for foedus::cache::CacheManagerPimpl:

Public Member Functions

 CacheManagerPimpl ()=delete
 
 CacheManagerPimpl (Engine *engine)
 
ErrorStack initialize_once () override
 
ErrorStack uninitialize_once () override
 
std::string describe () const
 
void handle_cleaner ()
 Main routine of cleaner_. More...
 
void handle_cleaner_evict_pages (uint64_t target_count)
 Evicts pages up to about target_count (maybe a bit more or less). More...
 
ErrorStack stop_cleaner ()
 
- Public Member Functions inherited from foedus::DefaultInitializable
 DefaultInitializable ()
 
virtual ~DefaultInitializable ()
 
 DefaultInitializable (const DefaultInitializable &)=delete
 
DefaultInitializableoperator= (const DefaultInitializable &)=delete
 
ErrorStack initialize () override final
 Typical implementation of Initializable::initialize() that provides initialize-once semantics. More...
 
ErrorStack uninitialize () override final
 Typical implementation of Initializable::uninitialize() that provides uninitialize-once semantics. More...
 
bool is_initialized () const override final
 Returns whether the object has been already initialized or not. More...
 
- Public Member Functions inherited from foedus::Initializable
virtual ~Initializable ()
 

Public Attributes

Engine *const engine_
 
std::thread cleaner_
 The only cleaner thread in this SOC engine. More...
 
uint64_t total_pages_
 
uint64_t cleaner_threshold_
 the number of allocated pages above which cleaner starts cleaning More...
 
uint64_t urgent_threshold_
 the number of allocated pages above which cleaner advances epoch to release pages More...
 
std::atomic< bool > stop_requested_
 to stop cleaner_ More...
 
memory::PagePoolpool_
 The SOC-local snapshot page pool in this SOC engine. More...
 
CacheHashtablehashtable_
 The cache hashtable (SnapshotPageId -> offset in pool) on top of the page pool. More...
 
memory::PagePoolOffsetreclaimed_pages_
 This buffers pages being reclaimed. More...
 
memory::AlignedMemory reclaimed_pages_memory_
 The memory backing reclaimed_pages_. More...
 
uint64_t reclaimed_pages_count_
 Number of pages buffered so far. More...
 

Constructor & Destructor Documentation

foedus::cache::CacheManagerPimpl::CacheManagerPimpl ( )
delete
foedus::cache::CacheManagerPimpl::CacheManagerPimpl ( Engine engine)
explicit

Definition at line 38 of file cache_manager_pimpl.cpp.

39  : engine_(engine),
40  stop_requested_(false),
41  pool_(nullptr),
42  hashtable_(nullptr),
43  reclaimed_pages_(nullptr),
45 }
memory::PagePoolOffset * reclaimed_pages_
This buffers pages being reclaimed.
CacheHashtable * hashtable_
The cache hashtable (SnapshotPageId -> offset in pool) on top of the page pool.
std::atomic< bool > stop_requested_
to stop cleaner_
memory::PagePool * pool_
The SOC-local snapshot page pool in this SOC engine.
uint64_t reclaimed_pages_count_
Number of pages buffered so far.

Member Function Documentation

std::string foedus::cache::CacheManagerPimpl::describe ( ) const

Definition at line 213 of file cache_manager_pimpl.cpp.

References foedus::memory::PagePool::Stat::allocated_pages_, cleaner_threshold_, engine_, foedus::Engine::get_soc_id(), foedus::memory::PagePool::get_stat(), pool_, reclaimed_pages_count_, reclaimed_pages_memory_, foedus::memory::PagePool::Stat::total_pages_, and urgent_threshold_.

Referenced by foedus::cache::CacheManager::describe(), handle_cleaner(), and uninitialize_once().

213  {
214  if (pool_ == nullptr) {
215  return "<SnapshotCacheManager />";
216  }
217 
218  std::stringstream str;
219  memory::PagePool::Stat pool_stat = pool_->get_stat();
220  str << "<SpCache "
221  << " node=\"" << engine_->get_soc_id() << "\""
222  << " total=\"" << pool_stat.total_pages_ << "\""
223  << " alloc=\"" << pool_stat.allocated_pages_ << "\""
224  << " threshold=\"" << cleaner_threshold_ << "\""
225  << " urgent_threshold=\"" << urgent_threshold_ << "\""
226  << " reclaimed_count=\"" << reclaimed_pages_count_ << "\""
227  << ">" << reclaimed_pages_memory_ << "</SpCache>";
228  return str.str();
229 }
Stat get_stat() const
Definition: page_pool.cpp:118
uint64_t urgent_threshold_
the number of allocated pages above which cleaner advances epoch to release pages ...
memory::PagePool * pool_
The SOC-local snapshot page pool in this SOC engine.
memory::AlignedMemory reclaimed_pages_memory_
The memory backing reclaimed_pages_.
uint64_t reclaimed_pages_count_
Number of pages buffered so far.
uint64_t cleaner_threshold_
the number of allocated pages above which cleaner starts cleaning
soc::SocId get_soc_id() const
If this is a child instance, returns its SOC ID (NUMA node).
Definition: engine.cpp:73

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::cache::CacheManagerPimpl::handle_cleaner ( )

Main routine of cleaner_.

Definition at line 119 of file cache_manager_pimpl.cpp.

References foedus::xct::XctManager::advance_current_global_epoch(), foedus::memory::PagePool::Stat::allocated_pages_, ASSERT_ND, cleaner_threshold_, describe(), foedus::debugging::StopWatch::elapsed_us(), engine_, foedus::xct::XctManager::get_current_global_epoch(), foedus::memory::PagePool::get_stat(), foedus::Engine::get_xct_manager(), handle_cleaner_evict_pages(), foedus::xct::XctManager::is_initialized(), foedus::assorted::memory_fence_acquire(), foedus::Epoch::one_more(), pool_, reclaimed_pages_, reclaimed_pages_count_, foedus::memory::PagePool::release(), foedus::debugging::StopWatch::stop(), stop_requested_, total_pages_, foedus::memory::PagePool::Stat::total_pages_, urgent_threshold_, and foedus::xct::XctManager::wait_for_current_global_epoch().

Referenced by initialize_once().

119  {
120  LOG(INFO) << "Here we go. Cleaner thread: " << describe();
121 
122  const uint32_t kIntervalMs = 5; // should be a bit shorter than epoch-advance interval
123  while (!stop_requested_) {
124  DVLOG(2) << "Cleaner thread came in: " << describe();
127  memory::PagePool::Stat stat = pool_->get_stat();
128  ASSERT_ND(stat.total_pages_ == total_pages_);
129  if (stat.allocated_pages_ > cleaner_threshold_) {
130  VLOG(0) << "Time to evict: " << describe();
131 
132  uint64_t target_count = stat.allocated_pages_ - cleaner_threshold_;
133  debugging::StopWatch evict_watch;
134  handle_cleaner_evict_pages(target_count);
135  evict_watch.stop();
136  VLOG(0) << "Evicted " << reclaimed_pages_count_ << " pages in " << evict_watch.elapsed_us()
137  << "us: " << describe();
138 
139  if (reclaimed_pages_count_ > 0) {
140  // We collected some number of pages in previous execution. now we have to wait for
141  // grace period before returning them to the pool as free pages.
142  xct::XctManager* xct_manager = engine_->get_xct_manager();
143  ASSERT_ND(xct_manager->is_initialized()); // see stop_cleaner()'s comment why this is true.
144  Epoch reclaimed_pages_epoch = xct_manager->get_current_global_epoch();
145  VLOG(0) << "Collected " << reclaimed_pages_count_ << " pages. let's return them to "
146  << "the pool: " << describe();
147  Epoch wait_until = reclaimed_pages_epoch.one_more();
148 
149  // We have to wait for grace-period, in other words until the next epoch.
150  if (stat.allocated_pages_ >= urgent_threshold_) {
151  VLOG(0) << "We are in urgent lack of free pages, let's advance epoch right now";
152  xct_manager->advance_current_global_epoch();
153  }
154  // wait forever, but occasionally wake up to check if the system is being shutdown
155  while (!stop_requested_ && xct_manager->get_current_global_epoch() < wait_until) {
156  const uint64_t interval_microsec = 100000ULL;
157  xct_manager->wait_for_current_global_epoch(wait_until, interval_microsec);
158  }
159 
160  if (!stop_requested_) {
161  Epoch current_epoch = xct_manager->get_current_global_epoch();
162  ASSERT_ND(reclaimed_pages_epoch < current_epoch);
163  VLOG(0) << "Okay! reclaimed_pages_epoch_=" << reclaimed_pages_epoch
164  << ", current_epoch=" << current_epoch;
165 
166  memory::PagePoolOffsetDynamicChunk chunk(reclaimed_pages_count_, reclaimed_pages_);
169  }
170  } else {
171  LOG(INFO) << "Wtf, we couldn't collect any pages? that's weird...: " << describe();
172  }
173 
174  if (stat.allocated_pages_ >= urgent_threshold_) {
175  LOG(INFO) << "Umm, still severely lacking free pages. This might mean"
176  " that the cleaner thread is getting behind or the pool is too small: " << describe();
177  }
178  } else {
179  DVLOG(2) << "Still enough free pages. do nothing";
180  }
181 
182  if (!stop_requested_) {
183  std::this_thread::sleep_for(std::chrono::milliseconds(kIntervalMs));
184  }
185  }
186 
187  LOG(INFO) << "Quiting... Cleaner thread: " << describe();
188 }
memory::PagePoolOffset * reclaimed_pages_
This buffers pages being reclaimed.
Stat get_stat() const
Definition: page_pool.cpp:118
std::atomic< bool > stop_requested_
to stop cleaner_
uint64_t urgent_threshold_
the number of allocated pages above which cleaner advances epoch to release pages ...
memory::PagePool * pool_
The SOC-local snapshot page pool in this SOC engine.
void handle_cleaner_evict_pages(uint64_t target_count)
Evicts pages up to about target_count (maybe a bit more or less).
void release(uint32_t desired_release_count, PagePoolOffsetChunk *chunk)
Returns the specified number of free pages from the chunk.
Definition: page_pool.cpp:134
xct::XctManager * get_xct_manager() const
See Transaction Manager.
Definition: engine.cpp:61
uint64_t reclaimed_pages_count_
Number of pages buffered so far.
uint64_t cleaner_threshold_
the number of allocated pages above which cleaner starts cleaning
void memory_fence_acquire()
Equivalent to std::atomic_thread_fence(std::memory_order_acquire).
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72

Here is the call graph for this function:

Here is the caller graph for this function:

void foedus::cache::CacheManagerPimpl::handle_cleaner_evict_pages ( uint64_t  target_count)

Evicts pages up to about target_count (maybe a bit more or less).

Results are written to reclaimed_pages_count_ and reclaimed_pages_.

Definition at line 190 of file cache_manager_pimpl.cpp.

References ASSERT_ND, foedus::cache::CacheHashtable::evict(), foedus::cache::CacheHashtable::EvictArgs::evicted_count_, hashtable_, reclaimed_pages_, and reclaimed_pages_count_.

Referenced by handle_cleaner().

190  {
192  ASSERT_ND(target_count > 0);
193  CacheHashtable::EvictArgs args = { target_count, 0, reclaimed_pages_ };
194  hashtable_->evict(&args);
195  reclaimed_pages_count_ = args.evicted_count_;
196 }
memory::PagePoolOffset * reclaimed_pages_
This buffers pages being reclaimed.
CacheHashtable * hashtable_
The cache hashtable (SnapshotPageId -> offset in pool) on top of the page pool.
void evict(EvictArgs *args)
Evict some entries from the hashtable.
uint64_t reclaimed_pages_count_
Number of pages buffered so far.
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorStack foedus::cache::CacheManagerPimpl::initialize_once ( )
overridevirtual

Implements foedus::DefaultInitializable.

Definition at line 47 of file cache_manager_pimpl.cpp.

References foedus::memory::AlignedMemory::alloc(), ASSERT_ND, foedus::EngineOptions::cache_, cleaner_, cleaner_threshold_, engine_, ERROR_STACK, foedus::memory::AlignedMemory::get_block(), foedus::memory::EngineMemory::get_local_memory(), foedus::Engine::get_memory_manager(), foedus::Engine::get_options(), foedus::memory::NumaNodeMemory::get_snapshot_cache_table(), foedus::memory::NumaNodeMemory::get_snapshot_pool(), foedus::Engine::get_soc_id(), foedus::memory::PagePool::get_stat(), foedus::thread::ThreadOptions::get_total_thread_count(), handle_cleaner(), hashtable_, foedus::DefaultInitializable::is_initialized(), foedus::Engine::is_master(), foedus::kErrorCodeDepedentModuleUnavailableInit, foedus::memory::AlignedMemory::kNumaAllocOnnode, foedus::kRetOk, foedus::EngineOptions::memory_, pool_, foedus::memory::MemoryOptions::private_page_pool_initial_grab_, reclaimed_pages_, reclaimed_pages_count_, reclaimed_pages_memory_, foedus::cache::CacheOptions::snapshot_cache_eviction_threshold_, foedus::cache::CacheOptions::snapshot_cache_urgent_threshold_, stop_requested_, foedus::EngineOptions::thread_, total_pages_, foedus::memory::PagePool::Stat::total_pages_, and urgent_threshold_.

Referenced by foedus::cache::CacheManager::initialize_once().

47  {
48  if (engine_->is_master()) {
49  // nothing to do in master engine
50  return kRetOk;
51  } else if (!engine_->get_memory_manager()->is_initialized()) {
53  }
54 
55  LOG(INFO) << "Initializing Snapshot Cache in Node-" << engine_->get_soc_id() << "...";
56 
57  memory::NumaNodeMemory* node = engine_->get_memory_manager()->get_local_memory();
58  pool_ = node->get_snapshot_pool();
59  hashtable_ = node->get_snapshot_cache_table();
61 
62  // So far, the reclaimed_pages_memory_ is large enough to hold all pages in the pool at once.
63  // This is obviously too much for most cases, but wouldn't be an issue as the memory consumption
64  // is anyway negligibly smaller than the page pool itself. Keep it simple stupid.
66  const CacheOptions& options = engine_->get_options().cache_;
67 
68  cleaner_threshold_ = total_pages_ * options.snapshot_cache_eviction_threshold_;
69  urgent_threshold_ = total_pages_ * options.snapshot_cache_urgent_threshold_;
70 
71  // exclude page counts initially grabbed by each thread.
72  uint64_t initial_allocations
75  cleaner_threshold_ += initial_allocations;
76  urgent_threshold_ += initial_allocations;
79  }
82  }
83 
87 
90  1ULL << 21,
92  engine_->get_soc_id());
94 
95  // launch the cleaner thread
96  stop_requested_.store(false);
97  cleaner_ = std::move(std::thread(&CacheManagerPimpl::handle_cleaner, this));
98 
99  return kRetOk;
100 }
numa_alloc_onnode() and numa_free().
memory::PagePoolOffset * reclaimed_pages_
This buffers pages being reclaimed.
#define ERROR_STACK(e)
Instantiates ErrorStack with the given foedus::error_code, creating an error stack with the current f...
uint32_t private_page_pool_initial_grab_
How many pages each NumaCoreMemory initially grabs when it is initialized.
CacheHashtable * hashtable_
The cache hashtable (SnapshotPageId -> offset in pool) on top of the page pool.
Stat get_stat() const
Definition: page_pool.cpp:118
uint32_t PagePoolOffset
Offset in PagePool that compactly represents the page address (unlike 8 bytes pointer).
Definition: memory_id.hpp:44
0x0005 : "GENERAL: A dependent module is not initialized yet. This implies a wrong initialization ord...
Definition: error_code.hpp:109
void alloc(uint64_t size, uint64_t alignment, AllocType alloc_type, int numa_node) noexcept
Allocate a memory, releasing the current memory if exists.
std::atomic< bool > stop_requested_
to stop cleaner_
uint64_t urgent_threshold_
the number of allocated pages above which cleaner advances epoch to release pages ...
memory::PagePool * pool_
The SOC-local snapshot page pool in this SOC engine.
const EngineOptions & get_options() const
Definition: engine.cpp:39
bool is_master() const
Returns if this engine object is a master instance.
Definition: engine.cpp:68
memory::AlignedMemory reclaimed_pages_memory_
The memory backing reclaimed_pages_.
memory::MemoryOptions memory_
std::thread cleaner_
The only cleaner thread in this SOC engine.
void * get_block() const
Returns the memory block.
thread::ThreadOptions thread_
NumaNodeMemory * get_local_memory() const
const ErrorStack kRetOk
Normal return value for no-error case.
uint64_t reclaimed_pages_count_
Number of pages buffered so far.
void handle_cleaner()
Main routine of cleaner_.
uint64_t cleaner_threshold_
the number of allocated pages above which cleaner starts cleaning
ThreadId get_total_thread_count() const
soc::SocId get_soc_id() const
If this is a child instance, returns its SOC ID (NUMA node).
Definition: engine.cpp:73
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
memory::EngineMemory * get_memory_manager() const
See Memory Manager.
Definition: engine.cpp:50
bool is_initialized() const override final
Returns whether the object has been already initialized or not.
cache::CacheOptions cache_

Here is the call graph for this function:

Here is the caller graph for this function:

ErrorStack foedus::cache::CacheManagerPimpl::stop_cleaner ( )

Definition at line 198 of file cache_manager_pimpl.cpp.

References cleaner_, foedus::kRetOk, and stop_requested_.

Referenced by foedus::cache::CacheManager::stop_cleaner(), and uninitialize_once().

198  {
199  bool original = false;
200  bool changed = stop_requested_.compare_exchange_strong(original, true);
201  if (changed) {
202  if (cleaner_.joinable()) {
203  LOG(INFO) << "Requesting Cache Cleaner to stop...";
204  cleaner_.join();
205  }
206  } else {
207  LOG(INFO) << "Cache Cleaner seems already stop-requested";
208  }
209  return kRetOk;
210 }
std::atomic< bool > stop_requested_
to stop cleaner_
std::thread cleaner_
The only cleaner thread in this SOC engine.
const ErrorStack kRetOk
Normal return value for no-error case.

Here is the caller graph for this function:

ErrorStack foedus::cache::CacheManagerPimpl::uninitialize_once ( )
overridevirtual

Implements foedus::DefaultInitializable.

Definition at line 102 of file cache_manager_pimpl.cpp.

References CHECK_ERROR, describe(), engine_, hashtable_, foedus::Engine::is_master(), foedus::kRetOk, pool_, reclaimed_pages_, reclaimed_pages_count_, reclaimed_pages_memory_, foedus::memory::AlignedMemory::release_block(), and stop_cleaner().

Referenced by foedus::cache::CacheManager::uninitialize_once().

102  {
103  if (engine_->is_master()) {
104  // nothing to do in master engine
105  return kRetOk;
106  }
107 
108  LOG(INFO) << "Uninitializing Snapshot Cache... " << describe();
110 
111  pool_ = nullptr;
112  hashtable_ = nullptr;
113  reclaimed_pages_ = nullptr;
116  return kRetOk;
117 }
memory::PagePoolOffset * reclaimed_pages_
This buffers pages being reclaimed.
void release_block()
Releases the memory block.
CacheHashtable * hashtable_
The cache hashtable (SnapshotPageId -> offset in pool) on top of the page pool.
memory::PagePool * pool_
The SOC-local snapshot page pool in this SOC engine.
bool is_master() const
Returns if this engine object is a master instance.
Definition: engine.cpp:68
memory::AlignedMemory reclaimed_pages_memory_
The memory backing reclaimed_pages_.
#define CHECK_ERROR(x)
This macro calls x and checks its returned value.
const ErrorStack kRetOk
Normal return value for no-error case.
uint64_t reclaimed_pages_count_
Number of pages buffered so far.

Here is the call graph for this function:

Here is the caller graph for this function:

Member Data Documentation

std::thread foedus::cache::CacheManagerPimpl::cleaner_

The only cleaner thread in this SOC engine.

In a master engine, this is not used.

Definition at line 70 of file cache_manager_pimpl.hpp.

Referenced by initialize_once(), and stop_cleaner().

uint64_t foedus::cache::CacheManagerPimpl::cleaner_threshold_

the number of allocated pages above which cleaner starts cleaning

Definition at line 73 of file cache_manager_pimpl.hpp.

Referenced by describe(), handle_cleaner(), and initialize_once().

Engine* const foedus::cache::CacheManagerPimpl::engine_
CacheHashtable* foedus::cache::CacheManagerPimpl::hashtable_

The cache hashtable (SnapshotPageId -> offset in pool) on top of the page pool.

This cache manager keeps checking In a master engine, this is null.

Definition at line 93 of file cache_manager_pimpl.hpp.

Referenced by handle_cleaner_evict_pages(), initialize_once(), and uninitialize_once().

memory::PagePool* foedus::cache::CacheManagerPimpl::pool_

The SOC-local snapshot page pool in this SOC engine.

This passively (no thread by itself) holds used pages and free pages. In a master engine, this is null.

Definition at line 85 of file cache_manager_pimpl.hpp.

Referenced by describe(), handle_cleaner(), initialize_once(), and uninitialize_once().

memory::PagePoolOffset* foedus::cache::CacheManagerPimpl::reclaimed_pages_

This buffers pages being reclaimed.

We reclaim pages after a grace period, rather than immediately after collecting them from the hashtable. Because of this epoch-based grace-period, we don't have to worry about thread-safety. This is super benefitial for simplicity and scalability. Because snapshot pages are immutable, that's all we have to do. Whereas, traditional bufferpools have to take care of dirty pages and singularity of page, so they can't just do grace-period. So far, the grace period is one epoch.

Definition at line 106 of file cache_manager_pimpl.hpp.

Referenced by handle_cleaner(), handle_cleaner_evict_pages(), initialize_once(), and uninitialize_once().

uint64_t foedus::cache::CacheManagerPimpl::reclaimed_pages_count_

Number of pages buffered so far.

Definition at line 112 of file cache_manager_pimpl.hpp.

Referenced by describe(), handle_cleaner(), handle_cleaner_evict_pages(), initialize_once(), and uninitialize_once().

memory::AlignedMemory foedus::cache::CacheManagerPimpl::reclaimed_pages_memory_

The memory backing reclaimed_pages_.

Definition at line 109 of file cache_manager_pimpl.hpp.

Referenced by describe(), initialize_once(), and uninitialize_once().

std::atomic<bool> foedus::cache::CacheManagerPimpl::stop_requested_

to stop cleaner_

Definition at line 77 of file cache_manager_pimpl.hpp.

Referenced by handle_cleaner(), initialize_once(), and stop_cleaner().

uint64_t foedus::cache::CacheManagerPimpl::total_pages_

Definition at line 71 of file cache_manager_pimpl.hpp.

Referenced by handle_cleaner(), and initialize_once().

uint64_t foedus::cache::CacheManagerPimpl::urgent_threshold_

the number of allocated pages above which cleaner advances epoch to release pages

Definition at line 75 of file cache_manager_pimpl.hpp.

Referenced by describe(), handle_cleaner(), and initialize_once().


The documentation for this class was generated from the following files: