diff --git a/algorithm/cs302/cache/CMakeLists.txt b/algorithm/cs302/cache/CMakeLists.txt index 46824e3a..b4ff9658 100644 --- a/algorithm/cs302/cache/CMakeLists.txt +++ b/algorithm/cs302/cache/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") enable_testing() -set(dependencies lru no fifo fifo_sc clock min) +set(dependencies lru no fifo fifo_sc clock min s3fifo) foreach (elementName IN LISTS dependencies) add_executable(${PROJECT_NAME}_${elementName}_test ${CMAKE_CURRENT_SOURCE_DIR}/${elementName}_cache.cpp) target_link_libraries(${PROJECT_NAME}_${elementName}_test CS203_DSAA_template_INCLUDE) diff --git a/algorithm/cs302/cache/cache_base.hpp b/algorithm/cs302/cache/cache_base.hpp index b3bcee9b..6beabfba 100644 --- a/algorithm/cs302/cache/cache_base.hpp +++ b/algorithm/cs302/cache/cache_base.hpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifndef CS203_DSAA_TEMPLATE_ALGORITHM_CACHE_CACHE_BASE_HPP #define CS203_DSAA_TEMPLATE_ALGORITHM_CACHE_CACHE_BASE_HPP diff --git a/algorithm/cs302/cache/clock_cache.cpp b/algorithm/cs302/cache/clock_cache.cpp index 2ee716c4..14664c27 100644 --- a/algorithm/cs302/cache/clock_cache.cpp +++ b/algorithm/cs302/cache/clock_cache.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifdef CS203_DSAA_TEST_MACRO @@ -21,27 +21,27 @@ static constexpr const auto init = true; namespace initFalse { static constexpr const std::array, 8> pairs{ { - {5, "4.data.in"}, {2, "sample.data.in"}, - {1177, "1.data.in"}, - {11848, "2.data.in"}, - {82382, "3.data.in"}, + {5, "4.data.in"}, {5, "5.data.in"}, {6, "6.data.in"}, {1, "7.data.in"}, + {1177, "1.data.in"}, + {11848, "2.data.in"}, + {82382, "3.data.in"}, }}; } namespace initTrue { static constexpr const std::array, 8> pairs{ { - {2, "4.data.in"}, {1, "sample.data.in"}, - {1193, "1.data.in"}, - {11826, "2.data.in"}, - {82382, "3.data.in"}, + {2, "4.data.in"}, {5, "5.data.in"}, {4, "6.data.in"}, {2, "7.data.in"}, + {1193, "1.data.in"}, + {11826, "2.data.in"}, + {82382, "3.data.in"}, }}; } namespace On { diff --git a/algorithm/cs302/cache/fifo_cache.cpp b/algorithm/cs302/cache/fifo_cache.cpp index f3763d1c..b52cd011 100644 --- a/algorithm/cs302/cache/fifo_cache.cpp +++ b/algorithm/cs302/cache/fifo_cache.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifdef CS203_DSAA_TEST_MACRO @@ -17,13 +17,13 @@ using std::array; static constexpr const std::array, 8> pairs{ { {1, "sample.data.in"}, - {1198, "1.data.in"}, - {11854, "2.data.in"}, - {82363, "3.data.in"}, {2, "4.data.in"}, {5, "5.data.in"}, {4, "6.data.in"}, {2, "7.data.in"}, + {1198, "1.data.in"}, + {11854, "2.data.in"}, + {82363, "3.data.in"}, }}; namespace On { diff --git a/algorithm/cs302/cache/fifo_sc_cache.cpp b/algorithm/cs302/cache/fifo_sc_cache.cpp index 1a66c14c..c11152c5 100644 --- a/algorithm/cs302/cache/fifo_sc_cache.cpp +++ b/algorithm/cs302/cache/fifo_sc_cache.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifdef CS203_DSAA_TEST_MACRO @@ -16,14 +16,14 @@ namespace cache::fifo_sc { using std::array; static constexpr const std::array, 8> pairs{ { - {5, "4.data.in"}, {2, "sample.data.in"}, - {1177, "1.data.in"}, - {11848, "2.data.in"}, - {82382, "3.data.in"}, + {5, "4.data.in"}, {5, "5.data.in"}, {6, "6.data.in"}, {1, "7.data.in"}, + {1177, "1.data.in"}, + {11848, "2.data.in"}, + {82382, "3.data.in"}, }}; namespace On { diff --git a/algorithm/cs302/cache/lru_cache.cpp b/algorithm/cs302/cache/lru_cache.cpp index b022fb85..b3bdc311 100644 --- a/algorithm/cs302/cache/lru_cache.cpp +++ b/algorithm/cs302/cache/lru_cache.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifdef CS203_DSAA_TEST_MACRO @@ -33,13 +33,13 @@ using std::array; static constexpr const std::array, 8> pairs{ { {1, "sample.data.in"}, - {1176, "1.data.in"}, - {11847, "2.data.in"}, - {82394, "3.data.in"}, {4, "4.data.in"}, {3, "5.data.in"}, {5, "6.data.in"}, {1, "7.data.in"}, + {1176, "1.data.in"}, + {11847, "2.data.in"}, + {82394, "3.data.in"}, }}; namespace On { diff --git a/algorithm/cs302/cache/min_cache.cpp b/algorithm/cs302/cache/min_cache.cpp index ff446fee..ca5f61b5 100644 --- a/algorithm/cs302/cache/min_cache.cpp +++ b/algorithm/cs302/cache/min_cache.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifdef CS203_DSAA_TEST_MACRO @@ -17,13 +17,13 @@ using std::array; static constexpr const std::array, 8> pairs{ { {2, "sample.data.in"}, - {4240, "1.data.in"}, - {43265, "2.data.in"}, - {88583, "3.data.in"}, {7, "4.data.in"}, {5, "5.data.in"}, {9, "6.data.in"}, {3, "7.data.in"}, + {4240, "1.data.in"}, + {43265, "2.data.in"}, + {88583, "3.data.in"}, }}; /** @@ -98,6 +98,7 @@ TEST_CASE("min test 1") { const auto input = inputs::read_input(); const auto inputAll = [&input] { vector vec{}; + vec.reserve(input.querys.size()); for (const auto ori: input.querys) { vec.push_back(ori); } diff --git a/algorithm/cs302/cache/no_cache.cpp b/algorithm/cs302/cache/no_cache.cpp index 084260bf..394da4c1 100644 --- a/algorithm/cs302/cache/no_cache.cpp +++ b/algorithm/cs302/cache/no_cache.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /* CS203_DSAA_template - Copyright (C) 2022-2023 nanoseeds + Copyright (C) 2022-2024 nanoseeds */ #ifdef CS203_DSAA_TEST_MACRO diff --git a/algorithm/cs302/cache/s3fifo_cache.cpp b/algorithm/cs302/cache/s3fifo_cache.cpp new file mode 100644 index 00000000..d4f49a4a --- /dev/null +++ b/algorithm/cs302/cache/s3fifo_cache.cpp @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +/* CS203_DSAA_template + Copyright (C) 2024 nanoseeds +*/ +#ifdef CS203_DSAA_TEST_MACRO + +#include +#include +#include +#include "cache_base.hpp" + +namespace cache::s3fifo { +using std::array; +static constexpr const std::array, 8> pairs{ + { + {1, "sample.data.in"}, + {4, "4.data.in"}, + {1, "5.data.in"}, + {4, "6.data.in"}, + {0, "7.data.in"}, + {1110, "1.data.in"}, + {11873, "2.data.in"}, + {82132, "3.data.in"}, + // 这种大规模数据集对比lru只差一点点, 性能很好. + // 更贴合实际的数据集应该能更好. + } +}; + +namespace Origin { +// algorithm come from +// https://blog.jasony.me/system/cache/2023/08/01/s3fifo +class fifo_cache final { +public: + std::deque> fifo{}; + size_t max_size{0}; + + explicit fifo_cache(size_t size) { + max_size = std::max(size_t(1), size); + } + + bool exists_const(size_t page) const { + const auto pointer = std::find_if(std::begin(fifo), std::end(fifo), + [page](const std::pair &pair) { + return pair.first == page; + }); + return pointer != std::end(fifo); + } + + bool exists(size_t page) { + const auto pointer = std::find_if(std::begin(fifo), std::end(fifo), + [page](const std::pair &pair) { + return pair.first == page; + }); + if (pointer == std::end(fifo)) { + return false; + } + pointer->second = std::min(3, pointer->second + 1); + return true; + } + + bool isFull() const { + return fifo.size() == max_size; + } + + bool isEmpty() const { + return fifo.empty(); + } + + std::pair pop() { + assert(!fifo.empty()); + const auto result = fifo.front(); + fifo.pop_front(); + return result; + } + + void insert(size_t page, size_t times) { + if (!isFull()) { + fifo.emplace_back(page, times); + } + } +}; + +class s3fifo_cache final : public cache_base { +private: + fifo_cache small; + fifo_cache main; + fifo_cache ghost; + + void insertToSmall(size_t page) { + if (small.isFull()) { + evictSmall(); + } + small.insert(page, 0); + } + + void insertToMain(size_t page, uint8_t times) { + if (main.isFull()) { + evictMain(); + } + main.insert(page, times); + } + + void insertToGhost(size_t page) { + if (!ghost.exists_const(page)) { + // 直接驱逐最后一个 + if (ghost.isFull()) { + ghost.pop(); + } + ghost.insert(page, 0); + } + } + + void evictSmall() { + bool evicted = false; + while (!evicted && !small.isEmpty()) { + const auto result = small.pop(); + if (result.second > 1) { + if (main.isFull()) { + evictMain(); + insertToMain(result.first, 0); + } + } else { + insertToGhost(result.first); + evicted = true; + } + } + } + + void evictMain() { + bool evicted = false; + while (!evicted && !main.isEmpty()) { + const auto result = main.pop(); + if (result.second > 0) { + insertToMain(result.first, result.second - 1); + } else { + evicted = true; + } + } + } + +public: + explicit s3fifo_cache(size_t page) : cache_base(page), small(page / 10), main(page * 9 / 10), + ghost(page * 9 / 10) {} + + virtual bool exists(size_t value) const override { + if (small.exists_const(value) || main.exists_const(value)) { + return true; + } + return false; + } + + // read true if match + virtual bool read(size_t page) override { + if (small.exists(page) || main.exists(page)) { + return true; + } // cache miss + if (ghost.exists_const(page)) { + insertToMain(page, 0); + } else { + insertToSmall(page); + } + return false; + } + + +}; + +TEST_CASE("fifo test n") { + for (const auto &[result, file_name]: pairs) { + const CS203_redirect cr{file_name}; + const auto input = inputs::read_input(); + const auto cache = std::make_unique(input.cacheSize); + size_t hits{0}; + for (const auto iter: input.querys) { + const auto exist = cache->read(iter); + hits += exist; + } + CHECK(result == hits); + } +} +} + +} +#endif diff --git a/algorithm/queue/README.md b/algorithm/queue/README.md new file mode 100644 index 00000000..c90d27d3 --- /dev/null +++ b/algorithm/queue/README.md @@ -0,0 +1,3 @@ +# queue + +TODO: using ring buffer to simulate a queue