Skip to content

Commit

Permalink
Optimize hot paths for JIT compilation (#9)
Browse files Browse the repository at this point in the history
Analyzed several hot paths via JIT Watch and optimized to enable better
JIT compilation and inlining.
  • Loading branch information
schlosna authored May 9, 2017
1 parent 9438ee5 commit e04731a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,18 @@ private static InvocationContext handlePreInvocation(InvocationEventHandler<? ex
try {
return handler.preInvocation(instance, method, args);
} catch (RuntimeException e) {
LOGGER.warn("Exception handling preInvocation({}): {}",
toInvocationDebugString(handler, instance, method, args), e.toString(), e);
preInvocationFailed(handler, instance, method, args, e);
return null;
}
return null;
}

private static void preInvocationFailed(InvocationEventHandler<? extends InvocationContext> handler,
Object instance, Method method, Object[] args, Exception exception) {
LOGGER.warn("Exception handling preInvocation({}): "
+ "invocation of {}.{} with arguments {} on {} threw: {}",
handler,
method.getDeclaringClass().getCanonicalName(), method.getName(), Arrays.toString(args), instance,
exception, exception);
}

private void handleSuccess(InvocationEventHandler<?> handler,
Expand All @@ -120,7 +128,7 @@ private void handleSuccess(InvocationEventHandler<?> handler,
handler.onSuccess(context, result);
} catch (RuntimeException e) {
LOGGER.warn("Exception handling onSuccess({}, {}): {}",
context, result, e.toString(), e);
context, result, e, e);
}
}

Expand All @@ -132,19 +140,10 @@ private void handleFailure(InvocationEventHandler<?> handler,
handler.onFailure(context, cause);
} catch (RuntimeException e) {
LOGGER.warn("Exception handling onFailure({}, {}): {}",
context, cause, e.toString(), e);
context, cause, e, e);
}
}

protected static String toInvocationDebugString(InvocationEventHandler<?> handler,
Object instance,
Method method,
Object[] args) {
return "invocation of " + handler + " on " + instance + " : "
+ method.getDeclaringClass() + '.' + method.getName()
+ " with arguments " + Arrays.toString(args);
}

static class CompositeInvocationContext extends DefaultInvocationContext {

private final InvocationContext[] contexts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,30 @@

public class DefaultInvocationContext implements InvocationContext {

private static final Object[] NO_ARGS = {};

private final long startTimeNanos;
private final Object instance;
private final Method method;
private final Object[] args;

protected DefaultInvocationContext(long startTimeNanos, Object instance, Method method, @Nullable Object[] args) {
this.startTimeNanos = startTimeNanos;
this.instance = checkNotNull(instance);
this.method = checkNotNull(method);
this.args = AbstractInvocationEventHandler.nullToEmpty(args).clone();
this.instance = instance;
this.method = method;
this.args = toNonNullClone(args);
}

private static Object[] toNonNullClone(@Nullable Object[] args) {
return args == null ? NO_ARGS : args.clone();
}

public static InvocationContext of(Object instance, Method method, @Nullable Object[] args) {
return new DefaultInvocationContext(System.nanoTime(), instance, method, args);
return new DefaultInvocationContext(
System.nanoTime(),
checkNotNull(instance, "instance"),
checkNotNull(method, "method"),
args);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ private boolean isEnabled(Object instance, Method method, Object[] args) {
return eventHandler.isEnabled()
&& filter.shouldInstrument(instance, method, args);
} catch (Throwable t) {
LOGGER.warn("Exception handling preInvocation({}): {}",
toInvocationDebugString(instance, method, args), t.toString(), t);
LOGGER.warn("Exception handling isEnabled({}): {}",
toInvocationDebugString(instance, method, args), t, t);
return false;
}
}
Expand Down Expand Up @@ -127,7 +127,7 @@ final InvocationContext handlePreInvocation(Object instance, Method method, Obje
return eventHandler.preInvocation(instance, method, args);
} catch (RuntimeException e) {
LOGGER.warn("Exception handling preInvocation({}): {}",
toInvocationDebugString(instance, method, args), e.toString(), e);
toInvocationDebugString(instance, method, args), e, e);
}
return null;
}
Expand All @@ -147,7 +147,7 @@ final Object handleOnSuccess(@Nullable InvocationContext context, @Nullable Obje
eventHandler.onSuccess(context, result);
} catch (RuntimeException e) {
LOGGER.warn("Exception handling onSuccess({}, {}): {}",
context, result, e.toString(), e);
context, result, e, e);
}
return result;
}
Expand All @@ -157,7 +157,7 @@ final Throwable handleOnFailure(@Nullable InvocationContext context, Throwable c
eventHandler.onFailure(context, cause);
} catch (RuntimeException e) {
LOGGER.warn("Exception handling onFailure({}, {}): {}",
context, cause, e.toString(), e);
context, cause, e, e);
}
return cause;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,53 +99,60 @@ public final void onFailure(@Nullable InvocationContext context, @Nonnull Throwa
return;
}

LOGGER.warn("Failed {}", cause, cause);
long durationNanos = System.nanoTime() - context.getStartTimeNanos();
logInvocation(context.getMethod(), context.getArgs(), durationNanos);
}

private void logInvocation(Method method, @Nullable Object[] nullableArgs, long durationNanos) {
if (isEnabled() && durationPredicate.test(durationNanos)) {
Object[] args = nullToEmpty(nullableArgs);
String messagePattern = getMessagePattern(args);
Object[] logParams = getLogParams(method, args, durationNanos, level);
log(messagePattern, logParams);
log(getMessagePattern(args), getLogParams(method, args, durationNanos, level));
}
}

private void log(String message, Object... args) {
if (level == LoggingLevel.TRACE) {
logger.trace(message, args);
} else if (level == LoggingLevel.DEBUG) {
logger.debug(message, args);
} else if (level == LoggingLevel.INFO) {
logger.info(message, args);
} else if (level == LoggingLevel.WARN) {
logger.warn(message, args);
} else if (level == LoggingLevel.ERROR) {
logger.error(message, args);
} else {
throw new IllegalArgumentException("Unsupported logging level " + level);
void log(String message, Object... args) {
switch (level) {
case TRACE:
logger.trace(message, args);
return;
case DEBUG:
logger.debug(message, args);
return;
case INFO:
logger.info(message, args);
return;
case WARN:
logger.warn(message, args);
return;
case ERROR:
logger.error(message, args);
return;
default:
throw invalidLoggingLevel(level);
}
}

static boolean isEnabled(Logger logger, LoggingLevel level) {
checkNotNull(level);
if (level == LoggingLevel.TRACE) {
return logger.isTraceEnabled();
} else if (level == LoggingLevel.DEBUG) {
return logger.isDebugEnabled();
} else if (level == LoggingLevel.INFO) {
return logger.isInfoEnabled();
} else if (level == LoggingLevel.WARN) {
return logger.isWarnEnabled();
} else if (level == LoggingLevel.ERROR) {
return logger.isErrorEnabled();
} else {
throw new IllegalArgumentException("Unsupported logging level " + level);
switch (level) {
case TRACE:
return logger.isTraceEnabled();
case DEBUG:
return logger.isDebugEnabled();
case INFO:
return logger.isInfoEnabled();
case WARN:
return logger.isWarnEnabled();
case ERROR:
return logger.isErrorEnabled();
default:
throw invalidLoggingLevel(level);
}
}

private static IllegalArgumentException invalidLoggingLevel(LoggingLevel level) {
return new IllegalArgumentException("Unsupported logging level " + level);
}

private static BooleanSupplier createEnabledSupplier(final Logger logger, final LoggingLevel level) {
checkNotNull(logger, "logger");
checkNotNull(level, "level");
Expand Down

0 comments on commit e04731a

Please sign in to comment.