Выполнение LRU в производственном коде

У меня есть код на С++, где мне нужно реализовать замену кэша с использованием техники LRU.
До сих пор я знаю два метода для выполнения замены LRU:

  • Использование timeStamp для каждого времени доступа к кэшированным данным и, наконец, сравнения временных элементов во время замены.
  • Использование стека кэшированных элементов и перемещение их вверх, если к ним обращаются в последнее время, так что, наконец, внизу будет содержать кандидат LRU.

Итак, какой из них лучше использовать в производственном коде?
Есть ли у них другие лучшие методы?

Ответ 1

Недавно я реализовал кеш LRU, используя связанный список, распространенный по карте хэша.

    /// Typedef for URL/Entry pair
    typedef std::pair< std::string, Entry > EntryPair;

    /// Typedef for Cache list
    typedef std::list< EntryPair > CacheList;

    /// Typedef for URL-indexed map into the CacheList
    typedef boost::unordered_map< std::string, CacheList::iterator > CacheMap;

    /// Cache LRU list
    CacheList mCacheList;

    /// Cache map into the list
    CacheMap mCacheMap;

Преимущество состоит в том, чтобы быть O (1) для всех важных операций.

Алгоритм вставки:

// create new entry
Entry iEntry( ... );

// push it to the front;
mCacheList.push_front( std::make_pair( aURL, iEntry ) );

// add it to the cache map
mCacheMap[ aURL ] = mCacheList.begin();

// increase count of entries
mEntries++;

// check if it time to remove the last element
if ( mEntries > mMaxEntries )
{
    // erease from the map the last cache list element
    mCacheMap.erase( mCacheList.back().first );

    // erase it from the list
    mCacheList.pop_back();

    // decrease count
    mEntries--;
}

Ответ 2

Вот очень простая реализация кеша LRU

https://github.com/lamerman/cpp-lru-cache.

Он прост в использовании и понимает, как он работает. Общий размер кода составляет около 50 строк.

Ответ 3

Для простоты, возможно, вам стоит рассмотреть возможность использования карты Boost MultiIndex. Если мы отделяем ключ от данных, мы поддерживаем несколько наборов ключей на одних и тех же данных.

Из [http://old.nabble.com/realization-of-Last-Recently-Used-cache-with-boost%3A%3Amulti_index-td22326432.html]:

"... использовать два индекса: 1) хэшировать для поиска значение по ключу 2) последовательно для отслеживания последних недавно использованных элементов (get function put item как последний элемент в секвенции). Если нам нужно удалить некоторые элементы из кеша, мы могут удалить их с начала последовательности).

Обратите внимание, что оператор "project" позволяет программисту эффективно перемещаться между различными индексами одного и того же multi_index_container.

Ответ 5

В нашей производственной среде мы используем двойной связанный список С++, который похож на связанный список ядра Linux. Красота заключается в том, что вы можете добавить объект к как можно большему количеству связанных списков, а список - быстро и просто.