9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "memory/metaspace/counters.hpp"
28 #include "memory/metaspace/freeBlocks.hpp"
29 //#define LOG_PLEASE
30 #include "metaspaceGtestCommon.hpp"
31
32 using metaspace::FreeBlocks;
33 using metaspace::SizeCounter;
34
35 #define CHECK_CONTENT(fb, num_blocks_expected, word_size_expected) \
36 { \
37 if (word_size_expected > 0) { \
38 EXPECT_FALSE(fb.is_empty()); \
39 } else { \
40 EXPECT_TRUE(fb.is_empty()); \
41 } \
42 EXPECT_EQ(fb.total_size(), (size_t)word_size_expected); \
43 EXPECT_EQ(fb.count(), (int)num_blocks_expected); \
44 }
45
46 class FreeBlocksTest {
47
48 FeederBuffer _fb;
49 FreeBlocks _freeblocks;
50
51 // random generator for block feeding
52 RandSizeGenerator _rgen_feeding;
53
54 // random generator for allocations (and, hence, deallocations)
55 RandSizeGenerator _rgen_allocations;
56
57 SizeCounter _allocated_words;
58
59 struct allocation_t {
60 allocation_t* next;
61 size_t word_size;
62 MetaWord* p;
63 };
64
65 // Array of the same size as the pool max capacity; holds the allocated elements.
66 allocation_t* _allocations;
67
68 int _num_allocs;
69 int _num_deallocs;
70 int _num_feeds;
71
72 bool feed_some() {
73 size_t word_size = _rgen_feeding.get();
74 MetaWord* p = _fb.get(word_size);
75 if (p != nullptr) {
76 _freeblocks.add_block(p, word_size);
77 return true;
78 }
79 return false;
80 }
81
82 bool deallocate_top() {
83
84 allocation_t* a = _allocations;
85 if (a != nullptr) {
86 _allocations = a->next;
87 check_marked_range(a->p, a->word_size);
88 _freeblocks.add_block(a->p, a->word_size);
89 delete a;
90 DEBUG_ONLY(_freeblocks.verify();)
91 return true;
92 }
93 return false;
94 }
95
96 void deallocate_all() {
97 while (deallocate_top());
98 }
99
100 bool allocate() {
101
102 size_t word_size = MAX2(_rgen_allocations.get(), _freeblocks.MinWordSize);
103 MetaWord* p = _freeblocks.remove_block(word_size);
104 if (p != nullptr) {
105 _allocated_words.increment_by(word_size);
106 allocation_t* a = new allocation_t;
107 a->p = p; a->word_size = word_size;
108 a->next = _allocations;
109 _allocations = a;
110 DEBUG_ONLY(_freeblocks.verify();)
111 mark_range(p, word_size);
112 return true;
113 }
114 return false;
115 }
116
117 void test_all_marked_ranges() {
118 for (allocation_t* a = _allocations; a != nullptr; a = a->next) {
119 check_marked_range(a->p, a->word_size);
120 }
121 }
122
123 void test_loop() {
124 // We loop and in each iteration execute one of three operations:
125 // - allocation from fbl
126 // - deallocation to fbl of a previously allocated block
127 // - feeding a new larger block into the fbl (mimicks chunk retiring)
128 // When we have fed all large blocks into the fbl (feedbuffer empty), we
129 // switch to draining the fbl completely (only allocs)
130 bool forcefeed = false;
131 bool draining = false;
132 bool stop = false;
133 int iter = 25000; // safety stop
134 while (!stop && iter > 0) {
135 iter --;
136 int surprise = (int)os::random() % 10;
137 if (!draining && (surprise >= 7 || forcefeed)) {
138 forcefeed = false;
139 if (feed_some()) {
140 _num_feeds++;
141 } else {
142 // We fed all input memory into the fbl. Now lets proceed until the fbl is drained.
143 draining = true;
144 }
145 } else if (!draining && surprise < 1) {
146 deallocate_top();
147 _num_deallocs++;
148 } else {
149 if (allocate()) {
150 _num_allocs++;
151 } else {
152 if (draining) {
153 stop = _freeblocks.total_size() < 512;
154 } else {
155 forcefeed = true;
156 }
157 }
158 }
159 if ((iter % 1000) == 0) {
160 DEBUG_ONLY(_freeblocks.verify();)
161 test_all_marked_ranges();
162 LOG("a %d (" SIZE_FORMAT "), d %d, f %d", _num_allocs, _allocated_words.get(), _num_deallocs, _num_feeds);
163 #ifdef LOG_PLEASE
164 _freeblocks.print(tty, true);
165 tty->cr();
166 #endif
167 }
168 }
169
170 // Drain
171
172 }
173
174 public:
175
176 FreeBlocksTest(size_t avg_alloc_size) :
177 _fb(512 * K), _freeblocks(),
178 _rgen_feeding(128, 4096),
179 _rgen_allocations(avg_alloc_size / 4, avg_alloc_size * 2, 0.01f, avg_alloc_size / 3, avg_alloc_size * 30),
180 _allocations(nullptr),
181 _num_allocs(0),
182 _num_deallocs(0),
183 _num_feeds(0)
184 {
185 CHECK_CONTENT(_freeblocks, 0, 0);
186 // some initial feeding
187 _freeblocks.add_block(_fb.get(1024), 1024);
188 CHECK_CONTENT(_freeblocks, 1, 1024);
189 }
190
191 ~FreeBlocksTest() {
192 deallocate_all();
193 }
194
195 static void test_small_allocations() {
196 FreeBlocksTest test(10);
197 test.test_loop();
198 }
199
200 static void test_medium_allocations() {
201 FreeBlocksTest test(30);
202 test.test_loop();
203 }
204
205 static void test_large_allocations() {
206 FreeBlocksTest test(150);
207 test.test_loop();
208 }
209
210 };
211
212 TEST_VM(metaspace, freeblocks_basics) {
213
214 FreeBlocks fbl;
215 MetaWord tmp[1024];
216 CHECK_CONTENT(fbl, 0, 0);
217
218 fbl.add_block(tmp, 1024);
219 DEBUG_ONLY(fbl.verify();)
220 ASSERT_FALSE(fbl.is_empty());
221 CHECK_CONTENT(fbl, 1, 1024);
222
223 MetaWord* p = fbl.remove_block(1024);
224 EXPECT_EQ(p, tmp);
225 DEBUG_ONLY(fbl.verify();)
226 CHECK_CONTENT(fbl, 0, 0);
227
228 }
229
230 TEST_VM(metaspace, freeblocks_small) {
231 FreeBlocksTest::test_small_allocations();
232 }
233
234 TEST_VM(metaspace, freeblocks_medium) {
235 FreeBlocksTest::test_medium_allocations();
236 }
237
238 TEST_VM(metaspace, freeblocks_large) {
239 FreeBlocksTest::test_large_allocations();
240 }
241
|
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "memory/metaspace/counters.hpp"
28 #include "memory/metaspace/freeBlocks.hpp"
29 #include "memory/metaspace/metablock.hpp"
30
31 //#define LOG_PLEASE
32 #include "metaspaceGtestCommon.hpp"
33
34 using metaspace::FreeBlocks;
35 using metaspace::MetaBlock;
36 using metaspace::SizeCounter;
37
38 #define CHECK_CONTENT(fb, num_blocks_expected, word_size_expected) \
39 { \
40 if (word_size_expected > 0) { \
41 EXPECT_FALSE(fb.is_empty()); \
42 } else { \
43 EXPECT_TRUE(fb.is_empty()); \
44 } \
45 EXPECT_EQ(fb.total_size(), (size_t)word_size_expected); \
46 EXPECT_EQ(fb.count(), (int)num_blocks_expected); \
47 }
48
49 TEST_VM(metaspace, freeblocks_basics) {
50
51 FreeBlocks fbl;
52 MetaWord tmp[1024];
53 CHECK_CONTENT(fbl, 0, 0);
54
55 MetaBlock bl(tmp, 1024);
56 fbl.add_block(bl);
57 DEBUG_ONLY(fbl.verify();)
58 ASSERT_FALSE(fbl.is_empty());
59 CHECK_CONTENT(fbl, 1, 1024);
60
61 MetaBlock bl2 = fbl.remove_block(1024);
62 ASSERT_EQ(bl, bl2);
63 DEBUG_ONLY(fbl.verify();)
64 CHECK_CONTENT(fbl, 0, 0);
65
66 }
|