Skip to content

Commit

Permalink
Abstract a class named ObjectCache and implement StoragePageCache usi…
Browse files Browse the repository at this point in the history
…ng ObjectCache.

Signed-off-by: trueeyu <lxhhust350@qq.com>
  • Loading branch information
trueeyu committed Feb 26, 2025
1 parent 94ee2c6 commit 9c49a91
Show file tree
Hide file tree
Showing 21 changed files with 1,177 additions and 126 deletions.
2 changes: 2 additions & 0 deletions be/src/cache/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ set(CACHE_FILES
block_cache/datacache_utils.cpp
block_cache/disk_space_monitor.cpp
block_cache/block_cache_hit_rate_counter.hpp
object_cache/lrucache_module.cpp
object_cache/object_cache.cpp
)

if (${WITH_STARCACHE} STREQUAL "ON")
Expand Down
61 changes: 61 additions & 0 deletions be/src/cache/object_cache/cache_module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "cache/object_cache/cache_types.h"
#include "common/status.h"
#include "util/slice.h"

namespace starrocks {

class ObjectCacheModule {
public:
virtual ~ObjectCacheModule() = default;

virtual Status init() = 0;

virtual Status insert(const std::string& key, void* value, size_t size, size_t charge, ObjectCacheDeleter deleter,
ObjectCacheHandlePtr* handle, ObjectCacheWriteOptions* options) = 0;

virtual Status lookup(const std::string& key, ObjectCacheHandlePtr* handle, ObjectCacheReadOptions* options) = 0;

virtual Status remove(const std::string& key) = 0;

virtual void release(ObjectCacheHandlePtr handle) = 0;

virtual const void* value(ObjectCacheHandlePtr handle) = 0;

virtual Slice value_slice(ObjectCacheHandlePtr handle) = 0;

virtual Status adjust_capacity(int64_t delta, size_t min_capacity) = 0;

virtual Status set_capacity(size_t capacity) = 0;

virtual size_t capacity() const = 0;

virtual size_t usage() const = 0;

virtual size_t lookup_count() const = 0;

virtual size_t hit_count() const = 0;

virtual const ObjectCacheMetrics metrics() const = 0;

virtual Status prune() = 0;

virtual Status shutdown() = 0;
};

} // namespace starrocks
80 changes: 80 additions & 0 deletions be/src/cache/object_cache/cache_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <functional>
#include <ostream>
#include <string>

// Not a good way to import lru cache header here, just for temporary compatibility with old deleters.
#include "util/lru_cache.h"

namespace starrocks {

enum class ObjectCacheModuleType { LRUCACHE, STARCACHE };

struct ObjectCacheOptions {
size_t capacity = 0;
ObjectCacheModuleType module = ObjectCacheModuleType::LRUCACHE;
};

struct ObjectCacheWriteOptions {
// The priority of the cache object, only support 0 and 1 now.
int8_t priority = 0;
// If ttl_seconds=0 (default), no ttl restriction will be set. If an old one exists, remove it.
uint64_t ttl_seconds = 0;
// If overwrite=true, the cache value will be replaced if it already exists.
bool overwrite = false;
// The probability to evict other items if the cache space is full, which can help avoid frequent cache replacement
// and improve cache hit rate sometimes.
// It is expressed as a percentage. If evict_probability is 10, it means the probability to evict other data is 10%.
int32_t evict_probability = 100;
};

struct ObjectCacheReadOptions {};

struct ObjectCacheHandle {};

struct ObjectCacheMetrics {
size_t capacity = 0;
size_t usage = 0;
size_t lookup_count = 0;
size_t hit_count = 0;
size_t object_item_count = 0;
};

using ObjectCacheHandlePtr = ObjectCacheHandle*;

// using CacheDeleter = std::function<void(const std::string&, void*)>;
//
// We only use the deleter function of the lru cache temporarily.
// Maybe a std::function object or a function pointer like `void (*)(std::string&, void*)` which
// independent on lru cache is more appropriate, but it is not easy to convert them to the lru
// cache deleter when using a lru cache module.
using ObjectCacheDeleter = void (*)(const CacheKey&, void*);

inline std::ostream& operator<<(std::ostream& os, const ObjectCacheModuleType& module) {
switch (module) {
case ObjectCacheModuleType::LRUCACHE:
os << "lrucache";
break;
case ObjectCacheModuleType::STARCACHE:
os << "starcache";
break;
}
return os;
}

} // namespace starrocks
147 changes: 147 additions & 0 deletions be/src/cache/object_cache/lrucache_module.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cache/object_cache/lrucache_module.h"

#include <butil/fast_rand.h>

#include "cache/status.h"
#include "common/logging.h"

namespace starrocks {

LRUCacheModule::~LRUCacheModule() {
if (!_cache) {
_cache->prune();
}
}

Status LRUCacheModule::init() {
if (!_cache) {
_cache.reset(new_lru_cache(_options.capacity));
}
return Status::OK();
}

Status LRUCacheModule::insert(const std::string& key, void* value, size_t size, size_t charge,
ObjectCacheDeleter deleter, ObjectCacheHandlePtr* handle,
ObjectCacheWriteOptions* options) {
if (!_check_write(charge, options)) {
return Status::InternalError("cache insertion is rejected");
}
auto* lru_handle = _cache->insert(key, value, charge, size, deleter, static_cast<CachePriority>(options->priority));
if (handle) {
*handle = reinterpret_cast<ObjectCacheHandlePtr>(lru_handle);
}
return Status::OK();
}

Status LRUCacheModule::lookup(const std::string& key, ObjectCacheHandlePtr* handle, ObjectCacheReadOptions* options) {
auto* lru_handle = _cache->lookup(CacheKey(key));
if (!lru_handle) {
return Status::NotFound("no such entry");
}
*handle = reinterpret_cast<ObjectCacheHandlePtr>(lru_handle);
return Status::OK();
}

Status LRUCacheModule::remove(const std::string& key) {
_cache->erase(CacheKey(key));
return Status::OK();
}

void LRUCacheModule::release(ObjectCacheHandlePtr handle) {
auto lru_handle = reinterpret_cast<Cache::Handle*>(handle);
_cache->release(lru_handle);
}

const void* LRUCacheModule::value(ObjectCacheHandlePtr handle) {
auto lru_handle = reinterpret_cast<Cache::Handle*>(handle);
return _cache->value(lru_handle);
}

Slice LRUCacheModule::value_slice(ObjectCacheHandlePtr handle) {
auto lru_handle = reinterpret_cast<Cache::Handle*>(handle);
return _cache->value_slice(lru_handle);
}

Status LRUCacheModule::adjust_capacity(int64_t delta, size_t min_capacity) {
if (_cache->adjust_capacity(delta, min_capacity)) {
return Status::OK();
}
return Status::InternalError("adjust quota failed");
}

Status LRUCacheModule::set_capacity(size_t capacity) {
_cache->set_capacity(capacity);
return Status::OK();
}

size_t LRUCacheModule::capacity() const {
return _cache->get_capacity();
}

size_t LRUCacheModule::usage() const {
return _cache->get_memory_usage();
}

size_t LRUCacheModule::lookup_count() const {
return _cache->get_lookup_count();
}

size_t LRUCacheModule::hit_count() const {
return _cache->get_hit_count();
}

const ObjectCacheMetrics LRUCacheModule::metrics() const {
ObjectCacheMetrics m;
m.capacity = _cache->get_capacity();
m.usage = _cache->get_memory_usage();
m.lookup_count = _cache->get_lookup_count();
m.hit_count = _cache->get_hit_count();
// Unsupported
m.object_item_count = 0;
return m;
}

Status LRUCacheModule::prune() {
_cache->prune();
return Status::OK();
}

Status LRUCacheModule::shutdown() {
_cache->prune();
return Status::OK();
}

bool LRUCacheModule::_check_write(size_t charge, ObjectCacheWriteOptions* options) const {
if (options->evict_probability >= 100) {
return true;
}
if (options->evict_probability <= 0) {
return false;
}

// TODO: The cost of this call may be relatively high, and it needs to be optimized later.
if (_cache->get_memory_usage() + charge <= _cache->get_capacity()) {
return true;
}

if (butil::fast_rand_less_than(100) < options->evict_probability) {
return true;
}
return false;
}

} // namespace starrocks
70 changes: 70 additions & 0 deletions be/src/cache/object_cache/lrucache_module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2021-present StarRocks, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "cache/object_cache/cache_module.h"
#include "util/lru_cache.h"

namespace starrocks {

class Cache;

class LRUCacheModule : public ObjectCacheModule {
public:
LRUCacheModule(const ObjectCacheOptions& options) : _options(options) {}

~LRUCacheModule();

Status init() override;

Status insert(const std::string& key, void* value, size_t size, size_t charge, ObjectCacheDeleter deleter,
ObjectCacheHandlePtr* handle, ObjectCacheWriteOptions* options) override;

Status lookup(const std::string& key, ObjectCacheHandlePtr* handle, ObjectCacheReadOptions* options) override;

Status remove(const std::string& key) override;

void release(ObjectCacheHandlePtr handle) override;

const void* value(ObjectCacheHandlePtr handle) override;

Slice value_slice(ObjectCacheHandlePtr handle) override;

Status adjust_capacity(int64_t delta, size_t min_capacity) override;

Status set_capacity(size_t capacity) override;

size_t capacity() const override;

size_t usage() const override;

size_t lookup_count() const override;

size_t hit_count() const override;

const ObjectCacheMetrics metrics() const override;

Status prune() override;

Status shutdown() override;

private:
bool _check_write(size_t charge, ObjectCacheWriteOptions* options) const;

ObjectCacheOptions _options;
std::shared_ptr<Cache> _cache;
};

} // namespace starrocks
Loading

0 comments on commit 9c49a91

Please sign in to comment.