Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java method takes seemingly lot of time that I cannot account for

Using JProfiler, I've identified a hot spot in my Java code that I cannot make sense of. JProfiler explains that this method takes 150μs (674μs without warmup) on average, not including the time it takes to call descendant methods. 150μs may not seem much, but in this application it adds up (and is experienced by my users) and also it seems a lot, compared to other methods that seem more complex to me than this one. Hence it matters to me.

private boolean assertReadAuthorizationForFields(Object entity, Object[] state,
        String[] propertyNames) {
    boolean changed = false;
    final List<Field> fields = FieldUtil.getAppropriatePropertyFields(entity, propertyNames);
    // average of 14 fields to iterate over
    for (final Field field : fields) {
        // manager.getAuthorization returns an enum type
        // manager is a field referencing another component
        if (manager.getAuthorization(READ, field).isDenied()) {
            FieldUtil.resetField(field.getName(), state, propertyNames);
            changed = true;
        }
    }
    return changed;
}

I have for myself minimized this method in different directions, but it never teaches me much useful. I cannot stress enough that the JProfiler-reported duration (150μs) is merely about the code in this method and does not include the time it takes to execute getAuthorization, isDenied, resetField and such. That is also why I start of by just posting this snippet, without much context, since the issue seems to be with this code and not its subsequent descendant method calls.

Maybe you can argue why – if you feel I'm seeing ghosts :) Anyhow, thanks for your time!

like image 780
Sander Verhagen Avatar asked Mar 17 '13 03:03

Sander Verhagen


1 Answers

Candidate behaviour that could slow you down:

  • Major effect: Obviously iteration. If you have lots of fields... You say 14 on average, which is fairly significant
  • Major effect: hotspot inlining would mean called methods are included in your times - and this could be noticeable because your method call(s) use reflection. getAppropriatePropertyFields introspects on class field definition metadata; resetField dynamically invokes setter methods (possibly using Method.invoke()??). If you are desperate for performance, you could use a cache via a HashSet (mapping ElementClass->FieldMetadataAndMethodHandle) This could contain field metadata and MethodHandles of setter methods (instead of using method.invoke, which is slow). Then you would only reflect during application startup and would use the JVM's fast dynamicInvoke support.
  • Minor effect - but multiplied by number of iterations: if you have very large arrays for state and property names, and they use primitive fields, then they would involve some degree of copying during method invocations (method parameters pass-by-'value' actually means pass-by-reference/pass-by-copy-of-primitives)
like image 77
Glen Best Avatar answered Oct 05 '22 12:10

Glen Best