1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2020 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 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 import java.util.ArrayList; 27 import java.util.Random; 28 29 /** 30 * RandomAllocator sits atop an arena and allocates from it. 31 * 32 * It will, according to an allocation profile, allocate random blocks in a certain size range and, from time to time, 33 * deallocate old blocks. 34 * 35 * At some point it will reach a limit: either the commit/reserve limit of the underlying MetaspaceTestContext, 36 * or the allocation ceiling imposed by the test. From that point on allocations will start failing. We can (and do) 37 * deallocate a bit more, but since that will only exercise the Arena's internal free block list and nothing much else, 38 * this is unexciting in terms of stressing Metaspace. So, the caller may decide to kill the arena and create a new one. 39 * 40 */ 41 public class RandomAllocator { 42 43 final MetaspaceTestArena arena; 44 final AllocationProfile profile; 45 46 ArrayList<Allocation> to_dealloc = new ArrayList<>(); 47 48 long ticks = 0; 49 boolean allocationError = false; 50 51 Random localRandom; 52 53 // Roll dice and return true if probability was hit 54 private boolean rollDice(double probability) { 55 return ((double)localRandom.nextInt(100) > (100.0 * (1.0 - probability))) ? true : false; 56 } 57 58 // Allocate a random amount from the arena. If dice hits right, add this to the deallocation list. 59 void allocateRandomly() { 60 allocationError = false; 61 long word_size = profile.randomAllocationSize(); 62 Allocation a = arena.allocate(word_size); 63 if (a != null) { 64 if (to_dealloc.size() < 10000) { 65 to_dealloc.add(a); 66 } 67 } else { 68 allocationError = true; 69 } 70 } 71 72 // Randomly choose one of the allocated in the deallocation list and deallocate it 73 void deallocateRandomly() { 74 if (to_dealloc.size() == 0) { 75 return; 76 } 77 int n = localRandom.nextInt(to_dealloc.size()); 78 Allocation a = to_dealloc.remove(n); 79 arena.deallocate(a); 80 } 81 82 public void tick() { 83 84 if (!allocationError) { 85 allocateRandomly(); 86 if(rollDice(profile.randomDeallocProbability)) { 87 deallocateRandomly(); 88 } 89 } else { 90 deallocateRandomly(); 91 allocationError = false; 92 } 93 94 ticks ++; 95 96 } 97 98 public RandomAllocator(MetaspaceTestArena arena) { 99 this.arena = arena; 100 this.profile = AllocationProfile.randomProfile(); 101 // reproducable randoms (we assume each allocator is only used from within one thread, and gets created from the main thread). 102 this.localRandom = new Random(RandomHelper.random().nextInt()); 103 } 104 105 106 @Override 107 public String toString() { 108 return arena.toString() + ", ticks=" + ticks; 109 } 110 111 }