Cache.inl 4.9 KB
Newer Older
J
jinhai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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
//
//   http://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.

S
starlord 已提交
18 19 20 21 22
namespace milvus {
namespace cache {

constexpr double DEFAULT_THRESHHOLD_PERCENT = 0.85;

Y
youny626 已提交
23
template <typename ItemObj>
S
starlord 已提交
24
Cache<ItemObj>::Cache(int64_t capacity, uint64_t cache_max_count)
Y
youny626 已提交
25 26
    : usage_(0), capacity_(capacity), freemem_percent_(DEFAULT_THRESHHOLD_PERCENT), lru_(cache_max_count) {
    //    AGENT_LOG_DEBUG << "Construct Cache with capacity " << std::to_string(mem_capacity)
S
starlord 已提交
27 28
}

Y
youny626 已提交
29
template <typename ItemObj>
S
starlord 已提交
30 31 32
void
Cache<ItemObj>::set_capacity(int64_t capacity) {
    if (capacity > 0) {
S
starlord 已提交
33 34 35 36 37
        capacity_ = capacity;
        free_memory();
    }
}

Y
youny626 已提交
38
template <typename ItemObj>
S
starlord 已提交
39 40
size_t
Cache<ItemObj>::size() const {
S
starlord 已提交
41 42 43 44
    std::lock_guard<std::mutex> lock(mutex_);
    return lru_.size();
}

Y
youny626 已提交
45
template <typename ItemObj>
S
starlord 已提交
46
bool
Y
youny626 已提交
47
Cache<ItemObj>::exists(const std::string& key) {
S
starlord 已提交
48 49 50 51
    std::lock_guard<std::mutex> lock(mutex_);
    return lru_.exists(key);
}

Y
youny626 已提交
52
template <typename ItemObj>
S
starlord 已提交
53
ItemObj
Y
youny626 已提交
54
Cache<ItemObj>::get(const std::string& key) {
S
starlord 已提交
55
    std::lock_guard<std::mutex> lock(mutex_);
S
starlord 已提交
56
    if (!lru_.exists(key)) {
S
starlord 已提交
57 58 59 60 61 62
        return nullptr;
    }

    return lru_.get(key);
}

Y
youny626 已提交
63
template <typename ItemObj>
S
starlord 已提交
64
void
Y
youny626 已提交
65
Cache<ItemObj>::insert(const std::string& key, const ItemObj& item) {
S
starlord 已提交
66
    if (item == nullptr) {
S
starlord 已提交
67 68 69
        return;
    }

Y
youny626 已提交
70 71 72 73 74
    //    if(item->size() > capacity_) {
    //        SERVER_LOG_ERROR << "Item size " << item->size()
    //                        << " is too large to insert into cache, capacity " << capacity_;
    //        return;
    //    }
S
starlord 已提交
75

Y
youny626 已提交
76
    // calculate usage
S
starlord 已提交
77 78 79
    {
        std::lock_guard<std::mutex> lock(mutex_);

Y
youny626 已提交
80
        // if key already exist, subtract old item size
S
starlord 已提交
81
        if (lru_.exists(key)) {
Y
youny626 已提交
82
            const ItemObj& old_item = lru_.get(key);
83
            usage_ -= old_item->Size();
S
starlord 已提交
84 85
        }

Y
youny626 已提交
86
        // plus new item size
87
        usage_ += item->Size();
S
starlord 已提交
88 89
    }

Y
youny626 已提交
90
    // if usage exceed capacity, free some items
S
starlord 已提交
91
    if (usage_ > capacity_) {
Y
youny626 已提交
92
        SERVER_LOG_DEBUG << "Current usage " << usage_ << " exceeds cache capacity " << capacity_
S
starlord 已提交
93 94 95 96
                         << ", start free memory";
        free_memory();
    }

Y
youny626 已提交
97
    // insert new item
S
starlord 已提交
98 99 100 101
    {
        std::lock_guard<std::mutex> lock(mutex_);

        lru_.put(key, item);
Y
youny626 已提交
102 103
        SERVER_LOG_DEBUG << "Insert " << key << " size:" << item->Size() << " bytes into cache, usage: " << usage_
                         << " bytes";
S
starlord 已提交
104 105 106
    }
}

Y
youny626 已提交
107
template <typename ItemObj>
S
starlord 已提交
108
void
Y
youny626 已提交
109
Cache<ItemObj>::erase(const std::string& key) {
S
starlord 已提交
110
    std::lock_guard<std::mutex> lock(mutex_);
S
starlord 已提交
111
    if (!lru_.exists(key)) {
S
starlord 已提交
112 113 114
        return;
    }

Y
youny626 已提交
115
    const ItemObj& old_item = lru_.get(key);
116
    usage_ -= old_item->Size();
S
starlord 已提交
117

118
    SERVER_LOG_DEBUG << "Erase " << key << " size: " << old_item->Size();
S
starlord 已提交
119 120 121 122

    lru_.erase(key);
}

Y
youny626 已提交
123
template <typename ItemObj>
S
starlord 已提交
124 125
void
Cache<ItemObj>::clear() {
S
starlord 已提交
126 127 128 129 130 131 132
    std::lock_guard<std::mutex> lock(mutex_);
    lru_.clear();
    usage_ = 0;
    SERVER_LOG_DEBUG << "Clear cache !";
}

/* free memory space when CACHE occupation exceed its capacity */
Y
youny626 已提交
133
template <typename ItemObj>
S
starlord 已提交
134 135
void
Cache<ItemObj>::free_memory() {
Y
youny626 已提交
136 137
    if (usage_ <= capacity_)
        return;
S
starlord 已提交
138 139 140

    int64_t threshhold = capacity_ * freemem_percent_;
    int64_t delta_size = usage_ - threshhold;
S
starlord 已提交
141
    if (delta_size <= 0) {
Y
youny626 已提交
142
        delta_size = 1;  // ensure at least one item erased
S
starlord 已提交
143 144 145 146 147 148 149 150 151 152
    }

    std::set<std::string> key_array;
    int64_t released_size = 0;

    {
        std::lock_guard<std::mutex> lock(mutex_);

        auto it = lru_.rbegin();
        while (it != lru_.rend() && released_size < delta_size) {
Y
youny626 已提交
153 154
            auto& key = it->first;
            auto& obj_ptr = it->second;
S
starlord 已提交
155 156

            key_array.emplace(key);
157
            released_size += obj_ptr->Size();
S
starlord 已提交
158 159 160 161 162 163
            ++it;
        }
    }

    SERVER_LOG_DEBUG << "to be released memory size: " << released_size;

Y
youny626 已提交
164
    for (auto& key : key_array) {
S
starlord 已提交
165 166 167 168 169 170
        erase(key);
    }

    print();
}

Y
youny626 已提交
171
template <typename ItemObj>
S
starlord 已提交
172 173
void
Cache<ItemObj>::print() {
S
starlord 已提交
174 175 176 177 178 179 180 181 182 183 184
    size_t cache_count = 0;
    {
        std::lock_guard<std::mutex> lock(mutex_);
        cache_count = lru_.size();
    }

    SERVER_LOG_DEBUG << "[Cache item count]: " << cache_count;
    SERVER_LOG_DEBUG << "[Cache usage]: " << usage_ << " bytes";
    SERVER_LOG_DEBUG << "[Cache capacity]: " << capacity_ << " bytes";
}

Y
youny626 已提交
185 186
}  // namespace cache
}  // namespace milvus