Cache .narinfo lookups

[?]
Feb 19, 2016, 3:19 PM
XLYHZUHTGM3HJBIINHPY4JLMENBFXPQEZYNEXENUOX3C47JLXJMAC

Dependencies

  • [2] SOB276BA Keep some statistics for the binary cache stores
  • [3] MB3TISH2 Rate-limit the number of threads copying closures at the same time
  • [4] 73YR46NJ hydra-queue-runner: Write directly to a binary cache
  • [5] 32HHP5CW hydra-queue-runner: Support generating a signed binary cache
  • [6] N2NKSKHS Refactor local binary cache code into a subclass
  • [7] ENXUSMSV Make concurrency more robust
  • [8] HPJKBFZ4 Handle concurrent finishing of the same build
  • [*] GH4S4AWM Rename file
  • [*] EOO4EFWD Use a single BinaryCacheStore for all threads
  • [*] 24BMQDZA Start of single-process hydra-queue-runner

Change contents

  • edit in src/hydra-queue-runner/binary-cache-store.cc at line 2
    [10.124]
    [3.1913]
    #include "sync.hh"
  • edit in src/hydra-queue-runner/binary-cache-store.cc at line 97
    [3.4304]
    [2.519]
    {
    auto state_(state.lock());
    auto res = state_->narInfoCache.get(storePath);
    if (res) {
    stats.narInfoReadAverted++;
    return **res;
    }
    }
  • replacement in src/hydra-queue-runner/binary-cache-store.cc at line 109
    [3.766][3.766:829](),[3.829][3.1633:1672](),[3.1633][3.1633:1672]()
    auto narInfo = NarInfo(getFile(narInfoFile), narInfoFile);
    assert(narInfo.path == storePath);
    [3.766]
    [3.5476]
    auto narInfo = make_ref<NarInfo>(getFile(narInfoFile), narInfoFile);
    assert(narInfo->path == storePath);
  • replacement in src/hydra-queue-runner/binary-cache-store.cc at line 113
    [3.1695][3.1695:1745]()
    if (!narInfo.checkSignature(*publicKeys))
    [3.1695]
    [3.1745]
    if (!narInfo->checkSignature(*publicKeys))
  • replacement in src/hydra-queue-runner/binary-cache-store.cc at line 117
    [3.5572][3.1841:1861]()
    return narInfo;
    [3.5572]
    [3.5588]
    {
    auto state_(state.lock());
    state_->narInfoCache.upsert(storePath, narInfo);
    stats.narInfoCacheSize = state_->narInfoCache.size();
    }
    return *narInfo;
  • edit in src/hydra-queue-runner/binary-cache-store.hh at line 5
    [3.9292]
    [2.657]
    #include "lru-cache.hh"
    #include "sync.hh"
  • edit in src/hydra-queue-runner/binary-cache-store.hh at line 28
    [11.423]
    [11.423]
    struct State
    {
    LRUCache<Path, ref<NarInfo>> narInfoCache{32 * 1024};
    };
    Sync<State> state;
  • edit in src/hydra-queue-runner/binary-cache-store.hh at line 54
    [2.747]
    [2.747]
    std::atomic<uint64_t> narInfoReadAverted{0};
  • edit in src/hydra-queue-runner/binary-cache-store.hh at line 56
    [2.794]
    [2.794]
    std::atomic<uint64_t> narInfoCacheSize{0};
  • edit in src/hydra-queue-runner/hydra-queue-runner.cc at line 594
    [2.2053]
    [2.2053]
    nested.attr("narInfoReadAverted", stats.narInfoReadAverted);
  • edit in src/hydra-queue-runner/hydra-queue-runner.cc at line 596
    [2.2114]
    [2.2114]
    nested.attr("narInfoCacheSize", stats.narInfoCacheSize);
  • file addition: lru-cache.hh (----------)
    [12.187]
    #pragma once
    #include <map>
    #include <list>
    /* A simple least-recently used cache. Not thread-safe. */
    template<typename Key, typename Value>
    class LRUCache
    {
    private:
    size_t maxSize;
    // Stupid wrapper to get around circular dependency between Data
    // and LRU.
    struct LRUIterator;
    using Data = std::map<Key, std::pair<LRUIterator, Value>>;
    using LRU = std::list<typename Data::iterator>;
    struct LRUIterator { typename LRU::iterator it; };
    Data data;
    LRU lru;
    public:
    LRUCache(size_t maxSize) : maxSize(maxSize) { }
    /* Insert or upsert an item in the cache. */
    void upsert(const Key & key, const Value & value)
    {
    erase(key);
    if (data.size() >= maxSize) {
    /* Retire the oldest item. */
    auto oldest = lru.begin();
    data.erase(*oldest);
    lru.erase(oldest);
    }
    auto res = data.emplace(key, std::make_pair(LRUIterator(), value));
    assert(res.second);
    auto & i(res.first);
    auto j = lru.insert(lru.end(), i);
    i->second.first.it = j;
    }
    bool erase(const Key & key)
    {
    auto i = data.find(key);
    if (i == data.end()) return false;
    lru.erase(i->second.first.it);
    data.erase(i);
    return true;
    }
    /* Look up an item in the cache. If it's exists, it becomes the
    most recently used item. */
    // FIXME: use boost::optional?
    Value * get(const Key & key)
    {
    auto i = data.find(key);
    if (i == data.end()) return 0;
    /* Move this item to the back of the LRU list. */
    lru.erase(i->second.first.it);
    auto j = lru.insert(lru.end(), i);
    i->second.first.it = j;
    return &i->second.second;
    }
    size_t size()
    {
    return data.size();
    }
    };
  • replacement in src/hydra-queue-runner/sync.hh at line 23
    [3.10091][3.10091:10110]()
    template <class T>
    [3.10091]
    [3.10110]
    template<class T>