Skip to content

Commit

Permalink
improve object cache expire effeciency
Browse files Browse the repository at this point in the history
  • Loading branch information
beef9999 committed Jun 28, 2024
1 parent 7c59780 commit efa8a09
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 25 deletions.
37 changes: 24 additions & 13 deletions common/expirecontainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ limitations under the License.
#include <photon/thread/thread.h>

ExpireContainerBase::ExpireContainerBase(uint64_t lifespan,
uint64_t timer_cycle)
uint64_t timer_cycle,
bool expire_if_possible)
: _lifespan(lifespan),
_timer(std::max(static_cast<uint64_t>(1000), timer_cycle),
{this, &ExpireContainerBase::expire}, true, 8UL * 1024 * 1024) {}
{this, &ExpireContainerBase::expire}, true),
_expire_if_possible(expire_if_possible) {}

auto ExpireContainerBase::insert(Item* item) -> std::pair<iterator, bool> {
return _set.emplace(item);
Expand All @@ -38,24 +40,31 @@ auto ExpireContainerBase::find(const Item& key_item) -> iterator {
}

void ExpireContainerBase::clear() {
for (auto x : ({
SCOPED_LOCK(_lock);
_list.node = nullptr;
Set(std::move(_set));
})) {
delete x;
Set tmp;
{
SCOPED_LOCK(_lock);
_list.node = nullptr;
tmp = std::move(_set);
}
for (auto x : tmp)
delete x;
}

uint64_t ExpireContainerBase::expire() {
({
if (_lifespan > UINT64_MAX / 2)
return 0;
intrusive_list<Item> expired;
{
SCOPED_LOCK(_lock);
_list.split_by_predicate([&](Item* x) {
auto tmp = _list.split_by_predicate([&](Item* x) {
bool ret = x->_timeout.expiration() < photon::now;
if (ret) _set.erase(x);
return ret;
});
}).delete_all();
expired = tmp;
tmp.node = nullptr;
}
expired.delete_all();
return 0;
}

Expand All @@ -79,7 +88,7 @@ auto ObjectCacheBase::ref_acquire(const Item& key_item,
uint64_t failure_cooldown) -> Item* {
Base::iterator holder;
Item* item = nullptr;
expire();
if (_expire_if_possible) expire();
do {
SCOPED_LOCK(_lock);
holder = Base::__find_prelock(key_item);
Expand Down Expand Up @@ -115,7 +124,9 @@ auto ObjectCacheBase::ref_acquire(const Item& key_item,
}

int ObjectCacheBase::ref_release(ItemPtr item, bool recycle) {
DEFER(expire());
DEFER({
if (_expire_if_possible) expire();
});
photon::semaphore sem;
{
SCOPED_LOCK(_lock);
Expand Down
19 changes: 8 additions & 11 deletions common/expirecontainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class ExpireContainerBase : public Object {
intrusive_list<Item> _list;
uint64_t _lifespan;
photon::Timer _timer;
bool _expire_if_possible;
photon::spinlock _lock; // protect _list/_set operations

using ItemPtr = Item*;
Expand All @@ -94,9 +95,6 @@ class ExpireContainerBase : public Object {
using Set = std::unordered_set<ItemPtr, ItemHash, ItemEqual>;
Set _set;

ExpireContainerBase(uint64_t lifespan, uint64_t timer_cycle);
~ExpireContainerBase() { clear(); }

using iterator = decltype(_set)::iterator;
std::pair<iterator, bool> insert(Item* item);
iterator begin() { return _set.begin(); }
Expand All @@ -121,6 +119,11 @@ class ExpireContainerBase : public Object {
}

public:
explicit ExpireContainerBase(uint64_t lifespan) : ExpireContainerBase(lifespan, lifespan / 16, true) {}
ExpireContainerBase(uint64_t lifespan, uint64_t timer_cycle) : ExpireContainerBase(lifespan, timer_cycle, true) {}
ExpireContainerBase(uint64_t lifespan, uint64_t timer_cycle, bool expire_if_possible);
~ExpireContainerBase() override { clear(); }

void clear();
uint64_t expire();
size_t size() { return _set.size(); }
Expand All @@ -134,9 +137,7 @@ template <typename KeyType, typename... Ts>
class ExpireContainer : public ExpireContainerBase {
public:
using Base = ExpireContainerBase;
ExpireContainer(uint64_t expiration) : Base(expiration, expiration / 16) {}
ExpireContainer(uint64_t expiration, uint64_t timer_cycle)
: Base(expiration, timer_cycle) {}
using Base::Base;

protected:
using KeyedItem = typename Base::KeyedItem<Base::Item, KeyType>;
Expand Down Expand Up @@ -198,7 +199,6 @@ class ExpireContainer : public ExpireContainerBase {

// a set / list like structure
// able to query whether an item not expired in it.

template <typename T>
class ExpireList : public ExpireContainer<T> {
public:
Expand Down Expand Up @@ -367,17 +367,14 @@ template <typename KeyType, typename ValType, typename ItemType>
class __ObjectCache : public ObjectCacheBase {
public:
using Base = ObjectCacheBase;
using Base::Base;
using Item = ItemType;
using KeyedItem = Base::KeyedItem<Base::Item, KeyType>;
using InterfaceKey = typename Item::InterfaceKey;
using ItemPtr = Item*;
using ValEntity = typename Item::ValEntity;
using Borrow = typename Base::Borrow<__ObjectCache>;

__ObjectCache(uint64_t expiration) : Base(expiration, expiration / 16) {}
__ObjectCache(uint64_t expiration, uint64_t timer_cycle)
: Base(expiration, timer_cycle) {}

template <typename Constructor>
ItemPtr ref_acquire(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
Expand Down
3 changes: 2 additions & 1 deletion thread/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace photon
// 0 for default_timeout (given in the ctor)
using Entry = Delegate<uint64_t>;

// Create a timer object with `default_timedout` in usec, callback function `on_timer`,
// Create a timer object with `default_timeout` in usec, callback function `on_timer`,
// and callback argument `arg`. The timer object is implemented as a special thread, so
// it has a `stack_size`, and the `on_timer` is invoked within the thread's context.
// The timer object is deleted automatically after it is finished.
Expand All @@ -39,6 +39,7 @@ namespace photon
{
_on_timer = on_timer;
_default_timeout = default_timeout;
_reset_timeout = -1UL;
_repeating = repeating;
_th = thread_create(&_stub, this, stack_size);
thread_enable_join(_th);
Expand Down

0 comments on commit efa8a09

Please sign in to comment.