use of org.graalvm.compiler.debug.GlobalMetrics in project graal by oracle.
the class CompileTheWorld method compile.
/**
* Compiles all methods in all classes in a given class path.
*
* @param classPath class path denoting classes to compile
* @throws IOException
*/
@SuppressWarnings("try")
private void compile(String classPath, LibGraalParams libgraal) throws IOException {
final String[] entries = classPath.split(File.pathSeparator);
Map<Thread, StackTraceElement[]> initialThreads = Thread.getAllStackTraces();
if (libgraal == null) {
try {
// compile dummy method to get compiler initialized outside of the
// config debug override.
HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(CompileTheWorld.class.getDeclaredMethod("dummy"));
int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
boolean useProfilingInfo = false;
boolean installAsDefault = false;
CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault);
task.runCompilation(compilerOptions);
} catch (NoSuchMethodException | SecurityException e1) {
printStackTrace(e1);
}
}
int startAtClass = startAt;
int stopAtClass = stopAt;
if (startAtClass >= stopAtClass) {
throw new IllegalArgumentException(String.format("StartAt (%d) must be less than StopAt (%d)", startAtClass, stopAtClass));
}
int startAtCompile = Options.StartAtCompile.getValue(harnessOptions);
int stopAtCompile = Options.StopAtCompile.getValue(harnessOptions);
if (startAtCompile >= stopAtCompile) {
throw new IllegalArgumentException(String.format("StartAtCompile (%d) must be less than StopAtCompile (%d)", startAtCompile, stopAtCompile));
}
int classStep = 1;
if (maxClasses != Integer.MAX_VALUE) {
int totalClassFileCount = 0;
for (String entry : entries) {
try (ClassPathEntry cpe = openClassPathEntry(entry)) {
if (cpe != null) {
totalClassFileCount += cpe.getClassNames().size();
}
}
}
int lastClassFile = totalClassFileCount - 1;
startAtClass = Math.min(startAt, lastClassFile);
stopAtClass = Math.min(stopAt, lastClassFile);
int range = stopAtClass - startAtClass + 1;
if (maxClasses < range) {
classStep = range / maxClasses;
}
}
TTY.println("CompileTheWorld : Gathering compilations ...");
Map<HotSpotResolvedJavaMethod, Integer> toBeCompiled = gatherCompilations(entries, startAtClass, stopAtClass, classStep);
/*
* Always use a thread pool, even for single threaded mode since it simplifies the use of
* DebugValueThreadFilter to filter on the thread names.
*/
int threadCount = 1;
if (Options.MultiThreaded.getValue(harnessOptions)) {
threadCount = Options.Threads.getValue(harnessOptions);
if (threadCount == 0) {
threadCount = Runtime.getRuntime().availableProcessors();
}
TTY.println("CompileTheWorld : Using %d threads", threadCount);
}
threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new CTWThreadFactory(libgraal));
TTY.println("CompileTheWorld : Starting compilations ...");
long start = System.nanoTime();
int compilationNum = 0;
int allCompiles = Math.min(toBeCompiled.size(), stopAtCompile) - Math.max(0, startAtCompile);
int maxCompiles = Options.MaxCompiles.getValue(harnessOptions);
float selector = Math.max(0, startAtCompile);
float selectorStep = maxCompiles < allCompiles ? (float) allCompiles / maxCompiles : 1.0f;
int repeat = Options.Repeat.getValue(harnessOptions);
long taskCount = 0;
for (Map.Entry<HotSpotResolvedJavaMethod, Integer> e : toBeCompiled.entrySet()) {
if (compilationNum >= startAtCompile && compilationNum < stopAtCompile) {
if (Math.round(selector) == compilationNum) {
for (int i = 0; i < repeat; i++) {
taskCount++;
threadPool.submit(new Runnable() {
@Override
public void run() {
compileMethod(e.getKey(), e.getValue(), libgraal);
}
});
}
selector += selectorStep;
}
}
compilationNum++;
}
int wakeups = 0;
long lastCompletedTaskCount = 0;
int statsInterval = Options.StatsInterval.getValue(harnessOptions);
long completedTaskCount;
do {
completedTaskCount = threadPool.getCompletedTaskCount();
if (completedTaskCount != 0 && (wakeups % statsInterval == 0 || completedTaskCount == taskCount)) {
long compilationsInInterval = completedTaskCount - lastCompletedTaskCount;
double rate = (double) compilationsInInterval / statsInterval;
long percent = completedTaskCount * 100 / taskCount;
TTY.println("CompileTheWorld : [%2d%%, %.1f compiles/s] %d of %d compilations completed, %d in last interval", percent, rate, completedTaskCount, taskCount, compilationsInInterval);
if (libgraal != null) {
armPrintMetrics();
}
lastCompletedTaskCount = completedTaskCount;
}
try {
threadPool.awaitTermination(1, TimeUnit.SECONDS);
wakeups++;
} catch (InterruptedException e) {
}
} while (completedTaskCount != taskCount);
threadPool.shutdown();
threadPool = null;
long elapsedTime = System.nanoTime() - start;
println();
int compiledClasses = classFileCounter > startAtClass ? classFileCounter - startAtClass : 0;
int compiledBytecodes = compileTimes.keySet().stream().collect(Collectors.summingInt(ResolvedJavaMethod::getCodeSize));
int compiledMethods = compileTimes.size();
long elapsedTimeSeconds = nanoToMillis(compileTime.get()) / 1_000;
double rateInMethods = (double) compiledMethods / elapsedTimeSeconds;
double rateInBytecodes = (double) compiledBytecodes / elapsedTimeSeconds;
TTY.println("CompileTheWorld : ======================== Done ======================");
TTY.println("CompileTheWorld : Compiled classes: %,d", compiledClasses);
TTY.println("CompileTheWorld : Compiled methods: %,d [%,d bytecodes]", compiledMethods, compiledBytecodes);
TTY.println("CompileTheWorld : Elapsed time: %,d ms", nanoToMillis(elapsedTime));
TTY.println("CompileTheWorld : Compile time: %,d ms", nanoToMillis(compileTime.get()));
TTY.println("CompileTheWorld : Compilation rate/thread: %,.1f methods/sec, %,.0f bytecodes/sec", rateInMethods, rateInBytecodes);
TTY.println("CompileTheWorld : HotSpot heap memory used: %,.3f MB", (double) memoryUsed.get() / 1_000_000);
TTY.println("CompileTheWorld : Huge methods skipped: %,d", hugeMethods.size());
int limit = Options.MetricsReportLimit.getValue(harnessOptions);
if (limit > 0) {
TTY.println("Longest compile times:");
compileTimes.entrySet().stream().sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue())).limit(limit).forEach(e -> {
long time = nanoToMillis(e.getValue());
ResolvedJavaMethod method = e.getKey();
TTY.println(" %,10d ms %s [bytecodes: %d]", time, method.format("%H.%n(%p)"), method.getCodeSize());
});
TTY.println("Largest methods skipped due to bytecode size exceeding HugeMethodLimit (%d):", getHugeMethodLimit(compiler.getGraalRuntime().getVMConfig()));
hugeMethods.entrySet().stream().sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue())).limit(limit).forEach(e -> {
ResolvedJavaMethod method = e.getKey();
TTY.println(" %,10d %s", e.getValue(), method.format("%H.%n(%p)"), method.getCodeSize());
});
}
GlobalMetrics metricValues = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMetricValues();
EconomicMap<MetricKey, Long> map = metricValues.asKeyValueMap();
Long compiledAndInstalledBytecodes = map.get(CompiledAndInstalledBytecodes);
Long compilationTime = map.get(CompilationTime);
if (compiledAndInstalledBytecodes != null && compilationTime != null) {
TTY.println("CompileTheWorld : Aggregate compile speed %d bytecodes per second (%d / %d)", (int) (compiledAndInstalledBytecodes / (compilationTime / 1000000000.0)), compiledAndInstalledBytecodes, compilationTime);
}
metricValues.print(compilerOptions);
metricValues.clear();
// Apart from the main thread, there should be only be daemon threads
// alive now. If not, then a class initializer has probably started
// a thread that could cause a deadlock while trying to exit the VM.
// One known example of this is sun.tools.jconsole.OutputViewer which
// spawns threads to redirect sysout and syserr. To help debug such
// scenarios, the stacks of potentially problematic threads are dumped.
Map<Thread, StackTraceElement[]> suspiciousThreads = new HashMap<>();
for (Map.Entry<Thread, StackTraceElement[]> e : Thread.getAllStackTraces().entrySet()) {
Thread thread = e.getKey();
if (thread != Thread.currentThread() && !initialThreads.containsKey(thread) && !thread.isDaemon() && thread.isAlive()) {
suspiciousThreads.put(thread, e.getValue());
}
}
if (!suspiciousThreads.isEmpty()) {
TTY.println("--- Non-daemon threads started during CTW ---");
for (Map.Entry<Thread, StackTraceElement[]> e : suspiciousThreads.entrySet()) {
Thread thread = e.getKey();
if (thread.isAlive()) {
TTY.println(thread.toString() + " " + thread.getState());
for (StackTraceElement ste : e.getValue()) {
TTY.println("\tat " + ste);
}
}
}
TTY.println("---------------------------------------------");
}
}
use of org.graalvm.compiler.debug.GlobalMetrics in project graal by oracle.
the class LibGraalEntryPoints method compileMethod.
/**
* The implementation of
* {@code org.graalvm.compiler.hotspot.test.CompileTheWorld.compileMethodInLibgraal()}.
*
* @param methodHandle the method to be compiled. This is a handle to a
* {@link HotSpotResolvedJavaMethod} in HotSpot's heap. A value of 0L can be passed
* to use this method for the side effect of initializing a
* {@link HotSpotGraalCompiler} instance without doing any compilation.
* @param useProfilingInfo specifies if profiling info should be used during the compilation
* @param installAsDefault specifies if the compiled code should be installed for the
* {@code Method*} associated with {@code methodHandle}
* @param printMetrics specifies if global metrics should be printed and reset
* @param optionsAddress native byte buffer storing a serialized {@link OptionValues} object
* @param optionsSize the number of bytes in the buffer
* @param optionsHash hash code of bytes in the buffer (computed with
* {@link Arrays#hashCode(byte[])})
* @param stackTraceAddress a native buffer in which a serialized stack trace can be returned.
* The caller will only read from this buffer if this method returns 0. A returned
* serialized stack trace is returned in this buffer with the following format:
*
* <pre>
* struct {
* int length;
* byte data[length]; // Bytes from a stack trace printed to a ByteArrayOutputStream.
* }
* </pre>
*
* where {@code length} truncated to {@code stackTraceCapacity - 4} if necessary
*
* @param stackTraceCapacity the size of the stack trace buffer
* @return a handle to a {@link InstalledCode} in HotSpot's heap or 0 if compilation failed
*/
@SuppressWarnings({ "unused", "try" })
@CEntryPoint(name = "Java_org_graalvm_compiler_hotspot_test_CompileTheWorld_compileMethodInLibgraal", include = LibGraalFeature.IsEnabled.class)
private static long compileMethod(PointerBase jniEnv, PointerBase jclass, @CEntryPoint.IsolateThreadContext long isolateThread, long methodHandle, boolean useProfilingInfo, boolean installAsDefault, boolean printMetrics, long optionsAddress, int optionsSize, int optionsHash, long stackTraceAddress, int stackTraceCapacity) {
try {
HotSpotJVMCIRuntime runtime = runtime();
HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler();
if (methodHandle == 0L) {
return 0L;
}
HotSpotResolvedJavaMethod method = LibGraal.unhand(HotSpotResolvedJavaMethod.class, methodHandle);
int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
try (CompilationContext scope = HotSpotGraalServices.openLocalCompilationContext(request)) {
OptionValues options = decodeOptions(optionsAddress, optionsSize, optionsHash);
CompilationTask task = new CompilationTask(runtime, compiler, request, useProfilingInfo, installAsDefault);
task.runCompilation(options);
HotSpotInstalledCode installedCode = task.getInstalledCode();
if (printMetrics) {
GlobalMetrics metricValues = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMetricValues();
metricValues.print(options);
metricValues.clear();
}
return LibGraal.translate(installedCode);
}
} catch (Throwable t) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
t.printStackTrace(new PrintStream(baos));
byte[] stackTrace = baos.toByteArray();
int length = Math.min(stackTraceCapacity - Integer.BYTES, stackTrace.length);
UNSAFE.putInt(stackTraceAddress, length);
UNSAFE.copyMemory(stackTrace, ARRAY_BYTE_BASE_OFFSET, null, stackTraceAddress + Integer.BYTES, length);
return 0L;
} finally {
/*
* libgraal doesn't use a dedicated reference handler thread, so we trigger the
* reference handling manually when a compilation finishes.
*/
Heap.getHeap().doReferenceHandling();
}
}
Aggregations