/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.preloading;
import org.jetbrains.kotlin.preloading.instrumentation.InterceptionInstrumenterAdaptor;
import org.jetbrains.kotlin.preloading.instrumentation.annotations.ClassName;
import org.jetbrains.kotlin.preloading.instrumentation.annotations.MethodDesc;
import org.jetbrains.kotlin.preloading.instrumentation.annotations.MethodInterceptor;
import org.jetbrains.kotlin.preloading.instrumentation.annotations.MethodName;
import java.io.PrintStream;
import java.util.*;
@SuppressWarnings("UnusedDeclaration")
public class ProfilingInstrumenterExample extends InterceptionInstrumenterAdaptor {
// How many times are visit* methods of visitors called?
@MethodInterceptor(className = ".*Visitor.*", methodName = "visit.*", methodDesc = ".*", allowMultipleMatches = true)
public static final Object a = new InvocationCount();
public static class InvocationCount {
private int count = 0;
public void enter() {
// This method is called upon entering a visit* method
count++;
}
public void dump(PrintStream out) {
// This method is called upon program termination
out.println("Invocation count: " + count);
}
}
// How much time do we spend in equals() methods of all classes inside package org
// NOTE: this works only on methods actually DECLARED in these classes
// This also logs names of actually instrumented methods to console
@MethodInterceptor(className = "org/.*", methodName = "equals", methodDesc = "\\(Ljava/lang/Object;\\)Z", logInterceptions = true)
public static final Object b = new TotalTime();
public static class TotalTime {
private long time = 0;
private long start = 0;
private boolean started = false;
public void enter() {
if (!started) {
start = System.nanoTime();
started = true;
}
}
public void exit() {
if (started) {
time += System.nanoTime() - start;
started = false;
}
}
public void dump(PrintStream out) {
out.printf("Total time: %.3fs\n", (time / 1e9));
}
}
// Collect all strings that were capitalized using StringUtil, and dump its instrumented byte code
@MethodInterceptor(className = "com/intellij/openapi/util/text/StringUtil",
methodName = "capitalize",
methodDesc = "\\(Ljava/lang/String;\\).*",
dumpByteCode = true)
public static Object c = new CollectFirstArguments();
public static class CollectFirstArguments {
private final List<Object> arguments = new ArrayList<>(30000);
public void enter(Object arg) {
arguments.add(arg);
}
public void dump(PrintStream out) {
out.println("Different values: " + new HashSet<>(arguments).size());
}
}
// What methods that have a long parameter followed by some object parameter are actually called
@MethodInterceptor(className = ".*",
methodName = ".*",
methodDesc = "\\(.*JL.*?\\).*",
allowMultipleMatches = true)
public static Object d = new MethodCollector();
public static class MethodCollector {
private final Collection<String> collected = new LinkedHashSet<>();
public void enter(@ClassName String className, @MethodName String name, @MethodDesc String desc) {
collected.add(className + "." + name + desc);
}
public void dump(PrintStream out) {
for (String s : collected) {
out.println(s);
}
}
}
// What integers are passed as first arguments to any methods?
@MethodInterceptor(className = ".*",
methodName = ".*",
methodDesc = "\\(.+\\).*",
allowMultipleMatches = true)
public static Object e = new FirstArgumentCollector() {
@Override
protected boolean accept(Object arg) {
return arg instanceof Integer;
}
};
public static abstract class FirstArgumentCollector {
private final Collection<Object> collected = new HashSet<>();
protected abstract boolean accept(Object arg);
public void enter(Object arg) {
if (accept(arg)) {
collected.add(arg);
}
}
public void dump(PrintStream out) {
out.println("Arguments: " + collected.size());
}
}
}