Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/test/runtime/NMT/MallocStressTest.java
32284 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @summary Stress test for malloc tracking26* @key nmt jcmd stress27* @library /testlibrary /testlibrary/whitebox28* @build MallocStressTest29* @run main ClassFileInstaller sun.hotspot.WhiteBox30* @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocStressTest31*/3233import java.util.concurrent.atomic.AtomicInteger;34import java.util.ArrayList;35import java.util.List;36import java.util.Random;37import com.oracle.java.testlibrary.*;38import sun.hotspot.WhiteBox;3940public class MallocStressTest {41private static int K = 1024;4243// The stress test runs in three phases:44// 1. alloc: A lot of malloc with fewer free, which simulates a burst memory allocation45// that is usually seen during startup or class loading.46// 2. pause: Pause the test to check accuracy of native memory tracking47// 3. release: Release all malloc'd memory and check native memory tracking result.48public enum TestPhase {49alloc,50pause,51release52};5354static TestPhase phase = TestPhase.alloc;5556// malloc'd memory57static ArrayList<MallocMemory> mallocd_memory = new ArrayList<MallocMemory>();58static long mallocd_total = 0;59static WhiteBox whiteBox;60static AtomicInteger pause_count = new AtomicInteger();6162static boolean is_64_bit_system;6364private static boolean is_64_bit_system() { return is_64_bit_system; }6566public static void main(String args[]) throws Exception {67is_64_bit_system = (Platform.is64bit());6869OutputAnalyzer output;70whiteBox = WhiteBox.getWhiteBox();7172// Grab my own PID73String pid = Integer.toString(ProcessTools.getProcessId());74ProcessBuilder pb = new ProcessBuilder();7576AllocThread[] alloc_threads = new AllocThread[256];77ReleaseThread[] release_threads = new ReleaseThread[64];7879int index;80// Create many allocation threads81for (index = 0; index < alloc_threads.length; index ++) {82alloc_threads[index] = new AllocThread();83}8485// Fewer release threads86for (index = 0; index < release_threads.length; index ++) {87release_threads[index] = new ReleaseThread();88}8990if (is_64_bit_system()) {91sleep_wait(2*60*1000);92} else {93sleep_wait(60*1000);94}95// pause the stress test96phase = TestPhase.pause;97while (pause_count.intValue() < alloc_threads.length + release_threads.length) {98sleep_wait(10);99}100101long mallocd_total_in_KB = (mallocd_total + K / 2) / K;102103// Now check if the result from NMT matches the total memory allocated.104String expected_test_summary = "Test (reserved=" + mallocd_total_in_KB +"KB, committed=" + mallocd_total_in_KB + "KB)";105// Run 'jcmd <pid> VM.native_memory summary'106pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});107output = new OutputAnalyzer(pb.start());108output.shouldContain(expected_test_summary);109110// Release all allocated memory111phase = TestPhase.release;112synchronized(mallocd_memory) {113mallocd_memory.notifyAll();114}115116// Join all threads117for (index = 0; index < alloc_threads.length; index ++) {118try {119alloc_threads[index].join();120} catch (InterruptedException e) {121}122}123124for (index = 0; index < release_threads.length; index ++) {125try {126release_threads[index].join();127} catch (InterruptedException e) {128}129}130131// All test memory allocated should be released132output = new OutputAnalyzer(pb.start());133output.shouldNotContain("Test (reserved=");134135// Verify that tracking level has not been downgraded136pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"});137output = new OutputAnalyzer(pb.start());138output.shouldNotContain("Tracking level has been downgraded due to lack of resources");139}140141private static void sleep_wait(int n) {142try {143Thread.sleep(n);144} catch (InterruptedException e) {145}146}147148149static class MallocMemory {150private long addr;151private int size;152153MallocMemory(long addr, int size) {154this.addr = addr;155this.size = size;156}157158long addr() { return this.addr; }159int size() { return this.size; }160}161162static class AllocThread extends Thread {163AllocThread() {164this.setName("MallocThread");165this.start();166}167168// AllocThread only runs "Alloc" phase169public void run() {170Random random = new Random();171while (MallocStressTest.phase == TestPhase.alloc) {172int r = Math.abs(random.nextInt());173// Only malloc small amount to avoid OOM174int size = r % 32;175if (is_64_bit_system()) {176r = r % 32 * K;177} else {178r = r % 64;179}180if (size == 0) size = 1;181long addr = MallocStressTest.whiteBox.NMTMallocWithPseudoStack(size, r);182if (addr != 0) {183MallocMemory mem = new MallocMemory(addr, size);184synchronized(MallocStressTest.mallocd_memory) {185MallocStressTest.mallocd_memory.add(mem);186MallocStressTest.mallocd_total += size;187}188} else {189System.out.println("Out of malloc memory");190break;191}192}193MallocStressTest.pause_count.incrementAndGet();194}195}196197static class ReleaseThread extends Thread {198private Random random = new Random();199ReleaseThread() {200this.setName("ReleaseThread");201this.start();202}203204public void run() {205while(true) {206switch(MallocStressTest.phase) {207case alloc:208slow_release();209break;210case pause:211enter_pause();212break;213case release:214quick_release();215return;216}217}218}219220private void enter_pause() {221MallocStressTest.pause_count.incrementAndGet();222while (MallocStressTest.phase != MallocStressTest.TestPhase.release) {223try {224synchronized(MallocStressTest.mallocd_memory) {225MallocStressTest.mallocd_memory.wait(10);226}227} catch (InterruptedException e) {228}229}230}231232private void quick_release() {233List<MallocMemory> free_list;234while (true) {235synchronized(MallocStressTest.mallocd_memory) {236if (MallocStressTest.mallocd_memory.isEmpty()) return;237int size = Math.min(MallocStressTest.mallocd_memory.size(), 5000);238List<MallocMemory> subList = MallocStressTest.mallocd_memory.subList(0, size);239free_list = new ArrayList<MallocMemory>(subList);240subList.clear();241}242for (int index = 0; index < free_list.size(); index ++) {243MallocMemory mem = free_list.get(index);244MallocStressTest.whiteBox.NMTFree(mem.addr());245}246}247}248249private void slow_release() {250try {251Thread.sleep(10);252} catch (InterruptedException e) {253}254synchronized(MallocStressTest.mallocd_memory) {255if (MallocStressTest.mallocd_memory.isEmpty()) return;256int n = Math.abs(random.nextInt()) % MallocStressTest.mallocd_memory.size();257MallocMemory mem = mallocd_memory.remove(n);258MallocStressTest.whiteBox.NMTFree(mem.addr());259MallocStressTest.mallocd_total -= mem.size();260}261}262}263}264265266