C++真正简单的 LRU 缓存的最佳容器

发布于 2024-11-18 14:52:46 字数 1842 浏览 6 评论 0原文

我需要实现一个非常简单的 LRU 缓存来存储内存地址。

  • 这些地址的计数是固定的(在运行时)。
  • 我只对最近使用的地址感兴趣(我不关心其他元素的顺序)。
  • 每个地址都有一个相应的索引号(简单整数),该索引号不是唯一的并且可以更改。

该实现需要以尽可能少的开销运行。除了每个地址之外,还有一个相关的信息结构(其中包含索引)。

我当前的方法是使用 std::list 来存储地址/信息对和 boost::unordered_multimap ,它是索引和相关迭代器之间的映射列表。

以下示例与我的生产代码无关。请注意,这只是为了更好地理解。

struct address_info
{
    address_info() : i(-1) {}
    int i;
    // more ...
};


int main()
{
    int const MAX_ADDR_COUNT = 10,
              MAX_ADDR_SIZE  = 64;

    char** s           = new char*[MAX_ADDR_COUNT];
    address_info* info = new address_info[MAX_ADDR_COUNT]();

    for (int i = 0; i < MAX_ADDR_COUNT; ++i)
        s[i] = new char[MAX_ADDR_SIZE]();

    typedef boost::unordered_multimap<int, std::list<std::pair<address_info, char*>>::const_iterator> index_address_map;

    std::list<std::pair<address_info, char*>> list(MAX_ADDR_COUNT);
    index_address_map                  map;

    {
        int i = 0;
        for (std::list<std::pair<address_info, char*>>::iterator iter = list.begin(); i != MAX_ADDR_COUNT; ++i, ++iter)
            *iter = std::make_pair(info[i], s[i]);
    }

    // usage example:
    // try to find address_info 4
    index_address_map::const_iterator iter = map.find(4);
    if (iter == map.end())
    {
        std::pair<address_info, char*>& lru = list.back();

        if (lru.first.i != -1)
            map.erase(lru.first.i);
        lru.first.i = 4;

        list.splice(list.begin(), list, boost::prior(list.end()));
        map.insert(std::make_pair(4, list.begin()));
    }
    else
        list.splice(list.begin(), list, iter->second);

    for (int i = 0; i < MAX_ADDR_COUNT; ++i)
        delete[] s[i];

    delete[] info;
    delete[] s;

    return 0;
}

I need to implement a really simple LRU cache which stores memory addresses.

  • The count of these addresses is fixed (at runtime).
  • I'm only interested in the last-recently used address (I don't care about the order of the other elements).
  • Each address has a corresponding index number (simple integer) which isn't unique and can change.

The implementation needs to run with as less overhead as possible. In addition to each address, there's is also a related info structure (which contains the index).

My current approach is using a std::list to store the address/info pair and a boost::unordered_multimap which is a mapping between the index and the related iterator of the list.

The following example has nothing to do with my production code. Please note, that this is just for a better understanding.

struct address_info
{
    address_info() : i(-1) {}
    int i;
    // more ...
};


int main()
{
    int const MAX_ADDR_COUNT = 10,
              MAX_ADDR_SIZE  = 64;

    char** s           = new char*[MAX_ADDR_COUNT];
    address_info* info = new address_info[MAX_ADDR_COUNT]();

    for (int i = 0; i < MAX_ADDR_COUNT; ++i)
        s[i] = new char[MAX_ADDR_SIZE]();

    typedef boost::unordered_multimap<int, std::list<std::pair<address_info, char*>>::const_iterator> index_address_map;

    std::list<std::pair<address_info, char*>> list(MAX_ADDR_COUNT);
    index_address_map                  map;

    {
        int i = 0;
        for (std::list<std::pair<address_info, char*>>::iterator iter = list.begin(); i != MAX_ADDR_COUNT; ++i, ++iter)
            *iter = std::make_pair(info[i], s[i]);
    }

    // usage example:
    // try to find address_info 4
    index_address_map::const_iterator iter = map.find(4);
    if (iter == map.end())
    {
        std::pair<address_info, char*>& lru = list.back();

        if (lru.first.i != -1)
            map.erase(lru.first.i);
        lru.first.i = 4;

        list.splice(list.begin(), list, boost::prior(list.end()));
        map.insert(std::make_pair(4, list.begin()));
    }
    else
        list.splice(list.begin(), list, iter->second);

    for (int i = 0; i < MAX_ADDR_COUNT; ++i)
        delete[] s[i];

    delete[] info;
    delete[] s;

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

山人契 2024-11-25 14:52:46

通常的建议是挖掘 Boost.MultiIndex 来完成任务:

  • 索引 0:插入顺序
  • 索引 1:元素的键(二分搜索或散列)

如果我没记错的话,它甚至在 Boost 网站上进行了演示。

The usual recommendation is to dig up Boost.MultiIndex for the task:

  • index 0: order of insertion
  • index 1: key of the element (either binary search or hash)

It's even demonstrated on Boost site if I recall correctly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文