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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// -*- C++ -*-
/*
The Hoard Multiprocessor Memory Allocator
www.hoard.org
Author: Emery Berger, http://www.emeryberger.com
Copyright (c) 1998-2020 Emery Berger
See the LICENSE file at the top-level directory of this
distribution and at http://github.com/emeryberger/Hoard.
*/
#ifndef HOARD_THRESHOLD_SEGHEAP_H
#define HOARD_THRESHOLD_SEGHEAP_H
namespace Hoard {
// Allows superheap to hold at least ThresholdSlop but no more than
// ThresholdFraction% more memory than client currently holds.
template <int ThresholdFraction, // % over current allowed in superheap.
int ThresholdSlop, // constant amount allowed in superheap.
int NumBins,
int (*getSizeClass) (const size_t),
size_t (*getClassMaxSize) (const int),
size_t MaxObjectSize,
class LittleHeap,
class BigHeap>
class ThresholdSegHeap : public BigHeap
{
public:
ThresholdSegHeap()
: _currLive (0),
_maxLive (0),
_maxFraction (1.0 + (double) ThresholdFraction / 100.0),
_cleared (false)
{}
size_t getSize (void * ptr) {
return BigHeap::getSize(ptr);
}
void * malloc (size_t sz) {
if (sz >= MaxObjectSize) {
return BigHeap::malloc (sz);
}
// Once the amount of cached memory in the superheap exceeds the
// desired threshold over max live requested by the client, dump
// it all.
const int sizeClass = getSizeClass (sz);
const size_t maxSz = getClassMaxSize (sizeClass);
if (sizeClass >= NumBins) {
return BigHeap::malloc (maxSz);
} else {
void * ptr = _heap[sizeClass].malloc (maxSz);
if (ptr == nullptr) {
return BigHeap::malloc (maxSz);
}
assert (getSize(ptr) <= maxSz);
_currLive += getSize (ptr);
if (_currLive >= _maxLive) {
_maxLive = _currLive;
_cleared = false;
}
return ptr;
}
}
void free (void * ptr) {
// Update current live memory stats, then free the object.
size_t sz = getSize(ptr);
if (sz >= MaxObjectSize) {
BigHeap::free (ptr);
return;
}
int cl = getSizeClass (sz);
if (cl >= NumBins) {
BigHeap::free (ptr);
return;
}
if (_currLive < sz) {
_currLive = 0;
} else {
_currLive -= sz;
}
_heap[cl].free (ptr);
bool crossedThreshold = (double) _maxLive > _maxFraction * (double) _currLive;
if ((_currLive > ThresholdSlop) && crossedThreshold && !_cleared)
{
// When we drop below the threshold, clear the heap.
for (int i = 0; i < NumBins; i++) {
_heap[i].clear();
}
// We won't clear again until we reach maxlive again.
_cleared = true;
_maxLive = _currLive;
}
}
private:
/// The current amount of live memory held by a client of this heap.
unsigned long _currLive;
/// The maximum amount of live memory held by a client of this heap.
unsigned long _maxLive;
/// Maximum fraction calculation.
const double _maxFraction;
/// Have we already cleared out the superheap?
bool _cleared;
LittleHeap _heap[NumBins];
};
}
#endif