Path: blob/master/test/hotspot/gtest/metaspace/test_freeblocks.cpp
41144 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2020 SAP SE. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "memory/metaspace/counters.hpp"27#include "memory/metaspace/freeBlocks.hpp"28//#define LOG_PLEASE29#include "metaspaceGtestCommon.hpp"3031using metaspace::FreeBlocks;32using metaspace::SizeCounter;3334#define CHECK_CONTENT(fb, num_blocks_expected, word_size_expected) \35{ \36if (word_size_expected > 0) { \37EXPECT_FALSE(fb.is_empty()); \38} else { \39EXPECT_TRUE(fb.is_empty()); \40} \41EXPECT_EQ(fb.total_size(), (size_t)word_size_expected); \42EXPECT_EQ(fb.count(), (int)num_blocks_expected); \43}4445class FreeBlocksTest {4647FeederBuffer _fb;48FreeBlocks _freeblocks;4950// random generator for block feeding51RandSizeGenerator _rgen_feeding;5253// random generator for allocations (and, hence, deallocations)54RandSizeGenerator _rgen_allocations;5556SizeCounter _allocated_words;5758struct allocation_t {59allocation_t* next;60size_t word_size;61MetaWord* p;62};6364// Array of the same size as the pool max capacity; holds the allocated elements.65allocation_t* _allocations;6667int _num_allocs;68int _num_deallocs;69int _num_feeds;7071bool feed_some() {72size_t word_size = _rgen_feeding.get();73MetaWord* p = _fb.get(word_size);74if (p != NULL) {75_freeblocks.add_block(p, word_size);76return true;77}78return false;79}8081void deallocate_top() {8283allocation_t* a = _allocations;84if (a != NULL) {85_allocations = a->next;86check_marked_range(a->p, a->word_size);87_freeblocks.add_block(a->p, a->word_size);88delete a;89DEBUG_ONLY(_freeblocks.verify();)90}91}9293bool allocate() {9495size_t word_size = MAX2(_rgen_allocations.get(), _freeblocks.MinWordSize);96MetaWord* p = _freeblocks.remove_block(word_size);97if (p != NULL) {98_allocated_words.increment_by(word_size);99allocation_t* a = new allocation_t;100a->p = p; a->word_size = word_size;101a->next = _allocations;102_allocations = a;103DEBUG_ONLY(_freeblocks.verify();)104mark_range(p, word_size);105return true;106}107return false;108}109110void test_all_marked_ranges() {111for (allocation_t* a = _allocations; a != NULL; a = a->next) {112check_marked_range(a->p, a->word_size);113}114}115116void test_loop() {117// We loop and in each iteration execute one of three operations:118// - allocation from fbl119// - deallocation to fbl of a previously allocated block120// - feeding a new larger block into the fbl (mimicks chunk retiring)121// When we have fed all large blocks into the fbl (feedbuffer empty), we122// switch to draining the fbl completely (only allocs)123bool forcefeed = false;124bool draining = false;125bool stop = false;126int iter = 100000; // safety stop127while (!stop && iter > 0) {128iter --;129int surprise = (int)os::random() % 10;130if (!draining && (surprise >= 7 || forcefeed)) {131forcefeed = false;132if (feed_some()) {133_num_feeds++;134} else {135// We fed all input memory into the fbl. Now lets proceed until the fbl is drained.136draining = true;137}138} else if (!draining && surprise < 1) {139deallocate_top();140_num_deallocs++;141} else {142if (allocate()) {143_num_allocs++;144} else {145if (draining) {146stop = _freeblocks.total_size() < 512;147} else {148forcefeed = true;149}150}151}152if ((iter % 1000) == 0) {153DEBUG_ONLY(_freeblocks.verify();)154test_all_marked_ranges();155LOG("a %d (" SIZE_FORMAT "), d %d, f %d", _num_allocs, _allocated_words.get(), _num_deallocs, _num_feeds);156#ifdef LOG_PLEASE157_freeblocks.print(tty, true);158tty->cr();159#endif160}161}162163// Drain164165}166167public:168169FreeBlocksTest(size_t avg_alloc_size) :170_fb(512 * K), _freeblocks(),171_rgen_feeding(128, 4096),172_rgen_allocations(avg_alloc_size / 4, avg_alloc_size * 2, 0.01f, avg_alloc_size / 3, avg_alloc_size * 30),173_allocations(NULL),174_num_allocs(0),175_num_deallocs(0),176_num_feeds(0)177{178CHECK_CONTENT(_freeblocks, 0, 0);179// some initial feeding180_freeblocks.add_block(_fb.get(1024), 1024);181CHECK_CONTENT(_freeblocks, 1, 1024);182}183184static void test_small_allocations() {185FreeBlocksTest test(10);186test.test_loop();187}188189static void test_medium_allocations() {190FreeBlocksTest test(30);191test.test_loop();192}193194static void test_large_allocations() {195FreeBlocksTest test(150);196test.test_loop();197}198199};200201TEST_VM(metaspace, freeblocks_basics) {202203FreeBlocks fbl;204MetaWord tmp[1024];205CHECK_CONTENT(fbl, 0, 0);206207fbl.add_block(tmp, 1024);208DEBUG_ONLY(fbl.verify();)209ASSERT_FALSE(fbl.is_empty());210CHECK_CONTENT(fbl, 1, 1024);211212MetaWord* p = fbl.remove_block(1024);213EXPECT_EQ(p, tmp);214DEBUG_ONLY(fbl.verify();)215CHECK_CONTENT(fbl, 0, 0);216217}218219TEST_VM(metaspace, freeblocks_small) {220FreeBlocksTest::test_small_allocations();221}222223TEST_VM(metaspace, freeblocks_medium) {224FreeBlocksTest::test_medium_allocations();225}226227TEST_VM(metaspace, freeblocks_large) {228FreeBlocksTest::test_large_allocations();229}230231232233