1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#pragma once
#include "base/logging.hpp"
#include "std/unordered_map.hpp"
#include "std/utility.hpp"
namespace search
{
namespace v2
{
template <class TKey, class TValue>
class Cache
{
unordered_map<TKey, TValue> m_map;
/// query statistics
size_t m_accesses;
size_t m_misses;
size_t m_emptyQueriesCount; /// empty queries count at a row
string m_name; /// cache name for print functions
public:
explicit Cache(string const & name)
: m_accesses(0), m_misses(0), m_emptyQueriesCount(0), m_name(name)
{
}
pair<TValue &, bool> Get(TKey const & key)
{
auto r = m_map.insert(make_pair(key, TValue()));
++m_accesses;
if (r.second)
++m_misses;
return pair<TValue &, bool>(r.first->second, r.second);
}
void Clear()
{
m_map.clear();
m_accesses = m_misses = 0;
m_emptyQueriesCount = 0;
}
/// Called at the end of every search query.
void ClearIfNeeded()
{
if (m_accesses != 0)
{
LOG(LDEBUG, ("Cache", m_name, "Queries =", m_accesses,
"From cache =", m_accesses - m_misses, "Added =", m_misses));
m_accesses = m_misses = 0;
m_emptyQueriesCount = 0;
}
else if (++m_emptyQueriesCount > 5)
{
LOG(LDEBUG, ("Clearing cache", m_name));
Clear();
}
}
};
} // namespace v2
} // namespace search
|