Path: blob/master/test/hotspot/jtreg/runtime/Metaspace/elastic/RandomAllocator.java
64507 views
/*1* Copyright (c) 2021 SAP SE. All rights reserved.2* Copyright (c) 2021, Oracle and/or its affiliates. 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*/2425import java.util.ArrayList;26import java.util.Random;2728/**29* RandomAllocator sits atop an arena and allocates from it.30*31* It will, according to an allocation profile, allocate random blocks in a certain size range and, from time to time,32* deallocate old blocks.33*34* At some point it will reach a limit: either the commit/reserve limit of the underlying MetaspaceTestContext,35* or the allocation ceiling imposed by the test. From that point on allocations will start failing. We can (and do)36* deallocate a bit more, but since that will only exercise the Arena's internal free block list and nothing much else,37* this is unexciting in terms of stressing Metaspace. So, the caller may decide to kill the arena and create a new one.38*39*/40public class RandomAllocator {4142final MetaspaceTestArena arena;43final AllocationProfile profile;4445ArrayList<Allocation> to_dealloc = new ArrayList<>();4647long ticks = 0;4849// Allocate (breathe in) until arena is full, then - to test the arena deallocator - deallocate some allocations50// and breathe in again until full.51boolean breatheIn = true;52int breatheOutTicks = 0;5354Random localRandom;5556// Roll dice and return true if probability was hit57private boolean rollDice(double probability) {58return ((double)localRandom.nextInt(100) > (100.0 * (1.0 - probability))) ? true : false;59}6061// Allocate a random amount from the arena. If dice hits right, add this to the deallocation list.62void allocateRandomly() {63long word_size = profile.randomAllocationSize();64Allocation a = arena.allocate(word_size);65if (a != null) {66if (to_dealloc.size() < 10000) {67to_dealloc.add(a);68}69} else {70// On allocation error, breathe out a bit71breatheIn = false;72breatheOutTicks = 0;73}74}7576// Randomly choose one of the allocated in the deallocation list and deallocate it77void deallocateRandomly() {78if (to_dealloc.size() == 0) {79return;80}81int n = localRandom.nextInt(to_dealloc.size());82Allocation a = to_dealloc.remove(n);83arena.deallocate(a);84}8586public void tick() {87if (breatheIn) {88// allocate until we hit the ceiling89allocateRandomly();90if (rollDice(profile.randomDeallocProbability)) {91deallocateRandomly();92}93} else {94if (++breatheOutTicks < 100) {95deallocateRandomly();96} else {97breatheIn = true;98}99}100ticks ++;101}102103public RandomAllocator(MetaspaceTestArena arena) {104this.arena = arena;105this.profile = AllocationProfile.randomProfile();106// reproducable randoms (we assume each allocator is only used from within one thread, and gets created from the main thread).107this.localRandom = new Random(RandomHelper.random().nextInt());108}109110long numAllocationFailures() {111return arena.numAllocationFailures;112}113114@Override115public String toString() {116return arena.toString() + ", ticks=" + ticks;117}118119}120121122