All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.imagej.patcher.MemoryProfiler Maven / Gradle / Ivy

Go to download

A runtime patcher to introduce extension points into the original ImageJ (1.x). This project offers extension points for use with ImageJ2 and it also offers limited support for headless operations.

There is a newer version: 1.2.7
Show newest version
/*
 * #%L
 * A light-weight, javassist-backed memory profiler.
 * %%
 * Copyright (C) 2012 Johannes Schindelin.
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of any organization.
 * #L%
 */

package net.imagej.patcher;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.Loader;
import javassist.NotFoundException;
import javassist.Translator;

/**
 * A very simple memory profiler.
 * 

* This memory profiler instruments all method entries and exists using * javassist. At each exit, it reports the relative memory usage, the total * memory usage, and the exit point of the current method. Call it like this: *

* *
 * ./fiji --main-class fiji.MemoryProfiler fiji.Main
 * 
*

* Since the memory profiling slows down execution dramatically due to the * synchronous output to stderr, you may want to limit the classes to be * instrumented by setting the environment variable MEMORY_PROFILE_ONLY to a * space-delimited list of classes. *

*

* If you want to instrument any class handled by IJPatcher, you need to use the * slightly more complicated command line: *

* *
 * ./fiji -Dpatch.ij1=false \
 *        --cp jars/javassist.jar --cp jars/ij1-patcher.jar \
 *        --cp jars/ij.jar --main-class net.imagej.patcher.MemoryProfiler \
 *        -- ij.ImageJ
 * 
*

* I wrote this class to profile the sudden resource hunger of Fiji Build and * figured that this class might come in handy in the future, or for others, or * both. *

* * @author Johannes Schindelin */ public class MemoryProfiler implements Translator { protected static final boolean debug = false; protected Set only; public MemoryProfiler() { this(System.getenv("MEMORY_PROFILE_ONLY")); } public MemoryProfiler(String only) { this(only == null ? null : Arrays.asList(only.split(" +"))); } public MemoryProfiler(Collection only) { if (only != null) { this.only = new HashSet(); this.only.addAll(only); } } public void start(ClassPool pool) throws NotFoundException, CannotCompileException { } public void onLoad(ClassPool pool, String classname) throws NotFoundException { // do not instrument yourself if (classname.equals(getClass().getName())) return; if (only != null && !only.contains(classname)) return; if (debug) System.err.println("instrumenting " + classname); CtClass cc = pool.get(classname); if (cc.isFrozen()) return; try { // instrument all methods and constructors for (CtMethod method : cc.getMethods()) handle(method); for (CtConstructor constructor : cc.getConstructors()) handle(constructor); } catch (RuntimeException e) { if (!e.getMessage().endsWith(" class is frozen")) e.printStackTrace(); } } protected void handle(CtBehavior behavior) { try { if (debug) System.err.println("instrumenting " + behavior.getClass().getName() + "." + behavior.getName()); if (behavior.isEmpty()) return; behavior.addLocalVariable("memoryBefore", CtClass.longType); behavior.insertBefore("memoryBefore = fiji.MemoryProfiler.get();"); behavior.insertAfter("fiji.MemoryProfiler.report(memoryBefore);"); } catch (CannotCompileException e) { if (!e.getMessage().equals("no method body")) e.printStackTrace(); } } protected static Runtime runtime = Runtime.getRuntime(); public static long get() { gc(); return runtime.totalMemory() - runtime.freeMemory(); } public static void report(long memoryBefore) { gc(); StackTraceElement[] trace = new Exception().getStackTrace(); StackTraceElement last = trace.length > 1 ? trace[1] : new StackTraceElement("null", "null", "null", -1); long current = get(); System.err.println("MemoryProfiler: " + (current - memoryBefore) + " " + current + " " + last.getClassName() + "." + last.getMethodName() + "(" + last.getFileName() + ":" + last.getLineNumber() + ")"); } public static void gc() { System.gc(); System.gc(); } public static void main(String[] args) throws Throwable { Thread.currentThread().setContextClassLoader(MemoryProfiler.class.getClassLoader()); if (args.length == 0) { System.err.println("Usage: java " + MemoryProfiler.class + " [...]"); System.exit(1); } String mainClass = args[0]; String[] mainArgs = new String[args.length - 1]; System.arraycopy(args, 1, mainArgs, 0, mainArgs.length); Loader loader = new Loader(); loader.addTranslator(ClassPool.getDefault(), new MemoryProfiler()); gc(); loader.run(mainClass, mainArgs); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy