Skip to content

Instantly share code, notes, and snippets.

@CalebWhiting
Last active December 4, 2017 21:59
Show Gist options
  • Save CalebWhiting/ef628ea8e1b6b30ca8f61adabd7019d5 to your computer and use it in GitHub Desktop.
Save CalebWhiting/ef628ea8e1b6b30ca8f61adabd7019d5 to your computer and use it in GitHub Desktop.
Demonstrates the effect of reflection on performance.
import java.lang.reflect.Method;
import java.util.stream.LongStream;
public class Main {
/**
* Run each test this many times to get a minimum, average, maximum value
*/
private static final int TEST_ATTEMPTS = 5000;
/**
* How many operations to perform per test
*/
private static final int THRESHOLD = 10_000_000;
/**
* The object to perform operations on
*/
private static final Object TARGET = new Object();
/**
* Optimise the reflection test
*/
private static final Method OBJECT_HASHCODE;
static {
try {
OBJECT_HASHCODE = Object.class.getDeclaredMethod("hashCode");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
long[] direct = new long[TEST_ATTEMPTS];
long directTime = test(Main::testDirect, direct);
long[] reflect = new long[TEST_ATTEMPTS];
long reflectTime = test(Main::testReflect, reflect);
System.out.printf("Completed %,d attempts (%,d operations per test)%n", TEST_ATTEMPTS, THRESHOLD);
System.out.printf("| -----------------------------------|%n");
System.out.printf("| Key | Direct | Reflect |%n");
System.out.printf("| ------------|----------|-----------|%n");
System.out.printf("| total-ms | % 8d | % 9d |%n", directTime, reflectTime);
System.out.printf("| min-time-ms | % 8d | % 9d |%n",
LongStream.of(direct).min().getAsLong(), LongStream.of(reflect).min().getAsLong());
System.out.printf("| max-time-ms | % 8d | % 9d |%n",
LongStream.of(direct).max().getAsLong(), LongStream.of(reflect).max().getAsLong());
System.out.printf("| avg-time-ms | %8s | %9s |%n",
LongStream.of(direct).average().getAsDouble(), LongStream.of(reflect).average().getAsDouble());
System.out.printf("| -----------------------------------|%n");
}
private static long test(Runnable func, long[] results) {
long totalStart = System.currentTimeMillis();
for (int n = 0; n < TEST_ATTEMPTS; n++) {
long funcStart = System.currentTimeMillis();
func.run();
results[n] = (System.currentTimeMillis() - funcStart);
}
return (System.currentTimeMillis() - totalStart);
}
/**
* Calls Object#hashCode directly
*/
private static void testDirect() {
for (int n = 0; n < THRESHOLD; n++) {
TARGET.hashCode();
}
}
/**
* Calls Object#hashCode via reflection.
* In reality it would be very hard to optimise all reflective calls to this degree in production
*/
private static void testReflect() {
try {
for (int n = 0; n < THRESHOLD; n++) {
OBJECT_HASHCODE.invoke(TARGET);
}
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment