Add a timer to the PAL
This adds a way to periodically pool the PAL to see if any timers have expired. Timers can be used to periodically provide callbacks to the rest of snmalloc.
This commit is contained in:
committed by
Matthew Parkinson
parent
c1062e629e
commit
20a114cb62
@@ -8,6 +8,7 @@
|
||||
#include "pool.h"
|
||||
#include "remotecache.h"
|
||||
#include "sizeclasstable.h"
|
||||
#include "ticker.h"
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
@@ -96,6 +97,11 @@ namespace snmalloc
|
||||
*/
|
||||
LocalCache* attached_cache;
|
||||
|
||||
/**
|
||||
* Ticker to query the clock regularly at a lower cost.
|
||||
*/
|
||||
Ticker<typename SharedStateHandle::Pal> ticker;
|
||||
|
||||
/**
|
||||
* The message queue needs to be accessible from other threads
|
||||
*
|
||||
@@ -405,6 +411,7 @@ namespace snmalloc
|
||||
std::cout << "Slab is woken up" << std::endl;
|
||||
#endif
|
||||
|
||||
ticker.check_tick();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -419,6 +426,7 @@ namespace snmalloc
|
||||
{
|
||||
dealloc_local_slabs(sizeclass);
|
||||
}
|
||||
ticker.check_tick();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +706,8 @@ namespace snmalloc
|
||||
sl.insert(meta);
|
||||
}
|
||||
|
||||
return finish_alloc<zero_mem, SharedStateHandle>(p, sizeclass);
|
||||
auto r = finish_alloc<zero_mem, SharedStateHandle>(p, sizeclass);
|
||||
return ticker.check_tick(r);
|
||||
}
|
||||
return small_alloc_slow<zero_mem>(sizeclass, fast_free_list, rsize);
|
||||
}
|
||||
@@ -766,7 +775,8 @@ namespace snmalloc
|
||||
alloc_classes[sizeclass].available.insert(meta);
|
||||
}
|
||||
|
||||
return finish_alloc<zero_mem, SharedStateHandle>(p, sizeclass);
|
||||
auto r = finish_alloc<zero_mem, SharedStateHandle>(p, sizeclass);
|
||||
return ticker.check_tick(r);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
97
src/mem/ticker.h
Normal file
97
src/mem/ticker.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ds/defines.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
/**
|
||||
* This class will attempt to call the PAL every 50ms to check the time.
|
||||
* If the caller of check_tick, does so more frequently, it will attempt
|
||||
* to back-off to only query the time, every n calls to check_tick, where
|
||||
* `n` adapts to the current frequency of calling.
|
||||
*
|
||||
* The aim is to reduce the time spent querying the time as this might be
|
||||
* an expensive operation if time has been virtualised.
|
||||
*/
|
||||
template<typename PAL>
|
||||
class Ticker
|
||||
{
|
||||
/**
|
||||
* Calls to check_tick required before the time is next queried
|
||||
*/
|
||||
uint64_t count_down = 1;
|
||||
|
||||
/**
|
||||
* Number of ticks next time we check the time.
|
||||
* That is,
|
||||
* counted - count_down
|
||||
* Is how many ticks, since last_epoch_ms was updated.
|
||||
*/
|
||||
uint64_t counted = 1;
|
||||
|
||||
/**
|
||||
* Last time we queried the clock.
|
||||
*/
|
||||
uint64_t last_query_ms = 0;
|
||||
|
||||
/**
|
||||
* Slow path that actually queries clock and sets up
|
||||
* how many calls for the next time we hit the slow path.
|
||||
*/
|
||||
template<typename T = void*>
|
||||
SNMALLOC_SLOW_PATH T check_tick_slow(T p = nullptr)
|
||||
{
|
||||
uint64_t now_ms = PAL::time_in_ms();
|
||||
|
||||
// Set up clock.
|
||||
if (last_query_ms == 0)
|
||||
{
|
||||
last_query_ms = now_ms;
|
||||
count_down = 1;
|
||||
counted = 1;
|
||||
return p;
|
||||
}
|
||||
|
||||
uint64_t duration_ms = now_ms - last_query_ms;
|
||||
last_query_ms = now_ms;
|
||||
|
||||
// Check is below clock resolution
|
||||
if (duration_ms == 0)
|
||||
{
|
||||
// Exponential back off
|
||||
count_down = counted;
|
||||
counted *= 2;
|
||||
return p;
|
||||
}
|
||||
|
||||
constexpr size_t deadline_in_ms = 50;
|
||||
|
||||
// Estimate number of ticks to get to the new deadline, based on the
|
||||
// current interval
|
||||
auto new_deadline_in_ticks =
|
||||
((1 + counted) * deadline_in_ms) / duration_ms;
|
||||
|
||||
counted = new_deadline_in_ticks;
|
||||
count_down = new_deadline_in_ticks;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename T = void*>
|
||||
SNMALLOC_FAST_PATH T check_tick(T p = nullptr)
|
||||
{
|
||||
// Check before decrement, so that later calcations can use
|
||||
// count_down == 0 for check on the next call.
|
||||
// This is used if the ticks are way below the frequency of
|
||||
// heart beat.
|
||||
if (--count_down == 0)
|
||||
{
|
||||
return check_tick_slow(p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
};
|
||||
} // namespace snmalloc
|
||||
Reference in New Issue
Block a user