Path: blob/master/test/hotspot/jtreg/runtime/Metaspace/elastic/MetaspaceTestContext.java
41155 views
1import sun.hotspot.WhiteBox;23import java.util.ArrayList;4import java.util.HashSet;5import java.util.List;67public class MetaspaceTestContext {89long context;1011final long commitLimit;12final long reserveLimit;1314int numArenasCreated;15int numArenasDestroyed;1617HashSet<MetaspaceTestArena> arenaList = new HashSet<>();1819long allocatedWords;20long numAllocated;21long deallocatedWords;22long numDeallocated;23long allocationFailures;2425public MetaspaceTestContext(long commitLimit, long reserveLimit) {26this.commitLimit = commitLimit;27this.reserveLimit = reserveLimit;28WhiteBox wb = WhiteBox.getWhiteBox();29context = wb.createMetaspaceTestContext(commitLimit, reserveLimit);30if (context == 0) {31throw new RuntimeException("Failed to create context");32}33}3435// no limits36public MetaspaceTestContext() {37this(0, 0);38}3940public void destroy() {41if (context != 0) {42WhiteBox wb = WhiteBox.getWhiteBox();43wb.destroyMetaspaceTestContext(context);44context = 0;45}46}4748public void purge() {49if (context != 0) {50WhiteBox wb = WhiteBox.getWhiteBox();51wb.purgeMetaspaceTestContext(context);52}53}5455public MetaspaceTestArena createArena(boolean is_micro, long ceiling) {56MetaspaceTestArena arena = null;57if (context != 0) {58WhiteBox wb = WhiteBox.getWhiteBox();59long arena0 = wb.createArenaInTestContext(context, is_micro);60if (arena0 == 0) {61throw new RuntimeException("Failed to create arena");62}63numArenasCreated++;64arena = new MetaspaceTestArena(arena0, ceiling);65arenaList.add(arena);66}67return arena;68}6970public void destroyArena(MetaspaceTestArena a) {71if (context != 0) {72if (a.isLive()) {73WhiteBox wb = WhiteBox.getWhiteBox();74wb.destroyMetaspaceTestArena(a.arena);75numArenasDestroyed++;76}77arenaList.remove(a);78}79}8081public long committedWords() {82long l = 0;83if (context != 0) {84WhiteBox wb = WhiteBox.getWhiteBox();85l = wb.getTotalCommittedWordsInMetaspaceTestContext(context);86}87return l;88}8990public long usedWords() {91long l = 0;92if (context != 0) {93WhiteBox wb = WhiteBox.getWhiteBox();94l = wb.getTotalUsedWordsInMetaspaceTestContext(context);95}96return l;97}9899public int numLiveArenas() {100return arenaList.size();101}102103public void updateTotals() {104allocatedWords = deallocatedWords = numAllocated = numDeallocated = 0;105for (MetaspaceTestArena a : arenaList) {106allocatedWords += a.allocatedWords;107deallocatedWords += a.deallocatedWords;108numAllocated += a.numAllocated;109numDeallocated += a.numDeallocated;110allocationFailures += a.numAllocationFailures;111}112}113114public void printToTTY() {115if (context != 0) {116WhiteBox wb = WhiteBox.getWhiteBox();117wb.printMetaspaceTestContext(context);118}119}120121/**122* Given usage and some context information for current live arenas, do a heuristic about whether the123* Usage seems right for this case.124*/125public void checkStatistics() {126127// Note:128// Estimating Used and Committed is fuzzy, and we only have limited information here129// (we know the current state, but not the history, which determines fragmentation and130// freelist occupancy).131//132// We do not want test which constantly generate false positives, so these checks are133// somewhat loose and only meant to check for clear outliers, e.g. leaks.134135///// used /////136137updateTotals();138139long usageMeasured = usedWords();140long committedMeasured = committedWords();141142if (usageMeasured > committedMeasured) {143throw new RuntimeException("Weirdness.");144}145146if (deallocatedWords > allocatedWords) {147throw new RuntimeException("Weirdness.");148}149150// If no arenas are alive, usage should be zero and committed too (in reclaiming mode)151if (numLiveArenas() == 0) {152if (usageMeasured > 0) {153throw new RuntimeException("Usage > 0, expected 0");154}155if (Settings.settings().doesReclaim()) {156if (committedMeasured > 0) {157throw new RuntimeException("Committed > 0, expected 0");158}159}160}161162long expectedMinUsage = allocatedWords - deallocatedWords;163164if (usageMeasured < expectedMinUsage) {165throw new RuntimeException("Usage too low: " + usageMeasured + " expected at least " + expectedMinUsage);166}167168long expectedMaxUsage = allocatedWords;169170// This is necessary a bit fuzzy, since Metaspace usage consists of:171// - whatever we allocated172// - deallocated blocks in fbl173// - remains of retired chunks in fbl174// - overhead per allocation (padding for alignment, possibly allocation guards)175176// Overhead per allocation (see metaspaceArena.cpp, get_raw_allocation_word_size() )177// Any allocation is 3 words least178expectedMaxUsage += (numAllocated * 3);179if (Settings.settings().usesAllocationGuards) {180// Guards need space.181expectedMaxUsage += (numAllocated * 2);182// Also, they disable the fbl, so deallocated still counts as used.183expectedMaxUsage += deallocatedWords;184}185186// Lets add a overhead per arena. Each arena carries a free block list containing187// deallocated/retired blocks. We do not know how much. In general, the free block list should not188// accumulate a lot of memory but be drained in the course of allocating memory from the arena.189long overheadPerArena = 1024 * 1024 * numLiveArenas();190expectedMaxUsage += overheadPerArena;191192if (expectedMaxUsage < usageMeasured) {193throw new RuntimeException("Usage seems high: " + usageMeasured + " expected at most " + expectedMaxUsage);194}195196///// Committed //////197198if (committedMeasured < expectedMinUsage) {199throw new RuntimeException("Usage too low: " + usageMeasured + " expected at least " + expectedMinUsage);200}201202// Max committed:203// This is difficult to estimate, so just a rough guess.204//205// Committed space depends on:206// 1) Usage (how much we allocated + overhead per allocation + free block list content)207// 2) free space in used chunks208// 3) committed chunks in freelist.209//210// Having only live usage numbers without history, (2) and (3) can only be roughly estimated. Since these211// are stress tests,212//213long expectedMaxCommitted = usageMeasured;214expectedMaxCommitted += Settings.rootChunkWordSize;215if (Settings.settings().doesReclaim()) {216expectedMaxCommitted *= 10.0;217} else {218expectedMaxCommitted *= 100.0;219}220221if (committedMeasured > expectedMaxCommitted) {222throw new RuntimeException("Committed seems high: " + committedMeasured + " expected at most " + expectedMaxCommitted);223}224225}226227@java.lang.Override228public java.lang.String toString() {229return "MetaspaceTestContext{" +230"context=" + context +231", commitLimit=" + commitLimit +232", reserveLimit=" + reserveLimit +233", numArenasCreated=" + numArenasCreated +234", numArenasDestroyed=" + numArenasDestroyed +235", numLiveArenas=" + numLiveArenas() +236", allocatedWords=" + allocatedWords +237", numAllocated=" + numAllocated +238", deallocatedWords=" + deallocatedWords +239", numDeallocated=" + numDeallocated +240", allocationFailures=" + allocationFailures +241'}';242}243}244245246