-
Notifications
You must be signed in to change notification settings - Fork 139
/
Copy pathFreeEntrySizeClassStats.hpp
146 lines (127 loc) · 6.87 KB
/
FreeEntrySizeClassStats.hpp
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*******************************************************************************
* Copyright IBM Corp. and others 2012
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#ifndef FREEENTRYSIZECLASSSTATS_HPP_
#define FREEENTRYSIZECLASSSTATS_HPP_
#include "omrcfg.h"
#include "omrcomp.h"
#include "spacesaving.h"
#include "Base.hpp"
#include "LightweightNonReentrantLock.hpp"
class MM_LargeObjectAllocateStats;
/**
* Keeps track of freeEntry size distribution in heap (per pool)
*/
class MM_FreeEntrySizeClassStats {
public:
struct FrequentAllocation {
uintptr_t _size; /**< frequent allocation size or a multiple of it */
FrequentAllocation *_nextInSizeClass;
/*TODO: there would be minus case for _count, make it intptr_t later */
uintptr_t _count;
};
private:
/*TODO: there would be minus case for _count, make it intptr_t later */
uintptr_t *_count; /**< base of an array of counters for each sizeClass */
FrequentAllocation **_frequentAllocationHead; /**< for each size class, there is a list of ascending (per size, not per count) frequent allocation (exact) sizes) */
uintptr_t _maxSizeClasses; /**< size of the above array */
FrequentAllocation *_frequentAllocation; /**< an array of FrequentAllocation structs of size _maxFrequentAllocateSizes (current size _frequentAllocateSizeCounters) */
FrequentAllocation *_veryLargeEntryPool; /**< an array of FrequentAllocation structs for veryLargeEntries */
FrequentAllocation *_freeHeadVeryLargeEntry; /**< the head of linklist of free veryLargeEntries */
float *_fractionFrequentAllocation; /**< fraction Array for cumulating the fraction of frequentAllocation during estimating fragmentation */
uintptr_t _maxFrequentAllocateSizes; /**< max size of _frequentAllocation array */
uintptr_t _maxVeryLargeEntrySizes; /**< max size of _veryLargeEntryPool array */
#define VERY_LARGE_ENTRY_POOL_SIZE_FOR_THREAD 3
uintptr_t _veryLargeEntrySizeClass; /**< index of sizeClass for minimum veryLargeEntry, the cache value of GCExtensions.largeObjectAllocationProfilingVeryLargeObjectSizeClass */
#define MAX_FREE_ENTRY_COUNTERS_PER_FREQ_ALLOC_SIZE 5
uintptr_t _frequentAllocateSizeCounters; /**< current size of _frequentAllocation array */
MM_LightweightNonReentrantLock _lock; /**< lock used during merge of thread local stats */
bool guarantyEnoughPoolSizeForVeryLargeEntry; /**< true for all memory pool, false for thread base */
private:
/**
* Take a snapshot of this structure stats.
* @param[out] stats structure where the snapshot is stored
* @param[in] sizes of all sizeclasses used to calculate total free memory returned
* @return total free memory represented by this structure
*/
uintptr_t copyTo(MM_FreeEntrySizeClassStats *stats, const uintptr_t sizeClassSizes[]);
FrequentAllocation* copyVeryLargeEntry(FrequentAllocation* entry);
public:
/* return count of 'regular' free entires (not those that are frequent allocates for a given size class */
uintptr_t getCount(uintptr_t sizeClassIndex) { return _count[sizeClassIndex]; }
uintptr_t getVeryLargeEntrySizeClass() { return _veryLargeEntrySizeClass; }
/* return count of all frequent allocate free entires */
uintptr_t getFrequentAllocCount(uintptr_t sizeClassIndex);
/* return the head of the lisf of all frequent allocate entries for a give size class */
FrequentAllocation *getFrequentAllocationHead(uintptr_t sizeClassIndex) { return _frequentAllocationHead[sizeClassIndex]; }
/* return total free memory represented by this structure */
uintptr_t getFreeMemory(const uintptr_t sizeClassSizes[]);
/* return the 'average' number of pages which can be freed */
uintptr_t getPageAlignedFreeMemory(const uintptr_t sizeClassSizes[], uintptr_t pageSize);
uintptr_t getMaxSizeClasses() { return _maxSizeClasses; }
/**< @param factorVeryLargeEntryPool : multiple factor for _maxVeryLargeEntrySizes, default = 1, double for splitFreeList case
* @param simulation : if true, generate _fractionFrequentAllocation array for cumulating fraction of frequentAllocation during estimating fragmentation, default = false
*/
bool initialize(MM_EnvironmentBase *env, uintptr_t maxAllocateSizes, uintptr_t maxSizeClasses, uintptr_t veryLargeObjectThreshold, uintptr_t factorVeryLargeEntryPool=1, bool simulation=false);
void tearDown(MM_EnvironmentBase *env);
/**< Reset counts for size class entries and for frequent allocations */
void resetCounts();
/**< Remove any frequent allocation sizes associated with size class entries,
* they will be rebuilt soon by initializeFrequentAllocation
*/
void clearFrequentAllocation();
/**< Merge the count of sizeClass with negative count of Very Large Entries
* correct inconsistent count, which is generated by the lack of size of VeryLargeObjectPool.
*/
void mergeCountForVeryLargeEntries();
/**< Merge provided stats with this free entry sizeClass stats */
void merge(MM_FreeEntrySizeClassStats *stats);
/**
* Merge provided stats with this free entry sizeClass stats
* Safe in multi-threaded environment.
* Provided stats cleared (thus ready for further gathering of current stats
*/
void mergeLocked(MM_FreeEntrySizeClassStats *stats) {
_lock.acquire();
merge(stats);
_lock.release();
stats->resetCounts();
}
/**< build the list of frequent allocation exact sizes for each size class */
void initializeFrequentAllocation(MM_LargeObjectAllocateStats *largeObjectAllocateStats);
/**< initialize veryLargeEntryPool -- link free veryLargeEntries in _freeHeadVeryLargeEntry list */
void initializeVeryLargeEntryPool();
friend class MM_LargeObjectAllocateStats;
MM_FreeEntrySizeClassStats() :
_count(NULL),
_frequentAllocationHead(NULL),
_maxSizeClasses(0),
_frequentAllocation(NULL),
_veryLargeEntryPool(NULL),
_fractionFrequentAllocation(NULL),
_maxFrequentAllocateSizes(0),
_maxVeryLargeEntrySizes(0),
_veryLargeEntrySizeClass(0),
_frequentAllocateSizeCounters(0)
{
}
};
#endif /* FREEENTRYSIZECLASSSTATS_HPP_ */