001/* 002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.test; 024 025import static com.oracle.graal.debug.internal.MemUseTrackerImpl.*; 026import jdk.internal.jvmci.hotspot.*; 027 028import com.oracle.graal.api.runtime.*; 029import com.oracle.graal.compiler.test.*; 030import com.oracle.graal.debug.*; 031import com.oracle.graal.debug.internal.*; 032import com.oracle.graal.hotspot.*; 033import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; 034 035/** 036 * Used to benchmark memory usage during Graal compilation. 037 * 038 * To benchmark: 039 * 040 * <pre> 041 * mx vm -XX:-UseJVMCIClassLoader -cp @com.oracle.graal.hotspot.test com.oracle.graal.hotspot.test.MemoryUsageBenchmark 042 * </pre> 043 * 044 * Memory analysis for a {@link CompileTheWorld} execution can also be performed. For example: 045 * 046 * <pre> 047 * mx --vm server vm -XX:-UseJVMCIClassLoader -G:CompileTheWorldClasspath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @com.oracle.graal.hotspot.test com.oracle.graal.hotspot.test.MemoryUsageBenchmark 048 * </pre> 049 */ 050public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { 051 052 public static int simple(int a, int b) { 053 return a + b; 054 } 055 056 public static synchronized int complex(CharSequence cs) { 057 if (cs instanceof String) { 058 return cs.hashCode(); 059 } 060 061 if (cs instanceof StringBuilder) { 062 int[] hash = {0}; 063 cs.chars().forEach(c -> hash[0] += c); 064 return hash[0]; 065 } 066 067 int res = 0; 068 069 // Exercise lock elimination 070 synchronized (cs) { 071 res = cs.length(); 072 } 073 synchronized (cs) { 074 res = cs.hashCode() ^ 31; 075 } 076 077 for (int i = 0; i < cs.length(); i++) { 078 res *= cs.charAt(i); 079 } 080 081 // A fixed length loop with some canonicalizable arithmetics will 082 // activate loop unrolling and more canonicalization 083 int sum = 0; 084 for (int i = 0; i < 5; i++) { 085 sum += i * 2; 086 } 087 res += sum; 088 089 // Activates escape-analysis 090 res += new String("asdf").length(); 091 092 return res; 093 } 094 095 static class MemoryUsageCloseable implements AutoCloseable { 096 097 private final long start; 098 private final String name; 099 100 public MemoryUsageCloseable(String name) { 101 this.name = name; 102 this.start = getCurrentThreadAllocatedBytes(); 103 } 104 105 @Override 106 public void close() { 107 long end = getCurrentThreadAllocatedBytes(); 108 long allocated = end - start; 109 System.out.println(name + ": " + allocated); 110 } 111 } 112 113 public static void main(String[] args) { 114 // Ensure a Graal runtime is initialized prior to Debug being initialized as the former 115 // may include processing command line options used by the latter. 116 Graal.getRuntime(); 117 118 // Ensure a debug configuration for this thread is initialized 119 if (Debug.isEnabled() && DebugScope.getConfig() == null) { 120 DebugEnvironment.initialize(System.out); 121 } 122 new MemoryUsageBenchmark().run(); 123 } 124 125 private void doCompilation(String methodName, String label) { 126 HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(methodName); 127 128 // invalidate any existing compiled code 129 method.reprofile(); 130 131 int id = method.allocateCompileId(jdk.internal.jvmci.compiler.Compiler.INVOCATION_ENTRY_BCI); 132 long graalEnv = 0L; 133 134 try (MemoryUsageCloseable c = label == null ? null : new MemoryUsageCloseable(label)) { 135 CompilationTask task = new CompilationTask(method, jdk.internal.jvmci.compiler.Compiler.INVOCATION_ENTRY_BCI, graalEnv, id, false); 136 task.runCompilation(); 137 } 138 } 139 140 private void allocSpyCompilation(String methodName) { 141 if (AllocSpy.isEnabled()) { 142 HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(methodName); 143 144 // invalidate any existing compiled code 145 method.reprofile(); 146 147 int id = method.allocateCompileId(jdk.internal.jvmci.compiler.Compiler.INVOCATION_ENTRY_BCI); 148 long graalEnv = 0L; 149 try (AllocSpy as = AllocSpy.open(methodName)) { 150 CompilationTask task = new CompilationTask(method, jdk.internal.jvmci.compiler.Compiler.INVOCATION_ENTRY_BCI, graalEnv, id, false); 151 task.runCompilation(); 152 } 153 } 154 } 155 156 private static final boolean verbose = Boolean.getBoolean("verbose"); 157 158 private void compileAndTime(String methodName) { 159 160 // Parse in eager mode to resolve methods/fields/classes 161 parseEager(methodName, AllowAssumptions.YES); 162 163 // Warm up and initialize compiler phases used by this compilation 164 for (int i = 0; i < 10; i++) { 165 doCompilation(methodName, verbose ? methodName + "[warmup-" + i + "]" : null); 166 } 167 168 doCompilation(methodName, methodName); 169 } 170 171 public void run() { 172 compileAndTime("simple"); 173 compileAndTime("complex"); 174 if (CompileTheWorld.Options.CompileTheWorldClasspath.getValue() != CompileTheWorld.SUN_BOOT_CLASS_PATH) { 175 CompileTheWorld ctw = new CompileTheWorld(); 176 try { 177 ctw.compile(); 178 } catch (Throwable e) { 179 e.printStackTrace(); 180 } 181 } 182 allocSpyCompilation("simple"); 183 allocSpyCompilation("complex"); 184 } 185}