Reduce boxing once.
Comment From: sbrannen
Thanks for the PR.
Executing javap -c spring-context/build/classes/java/main/org/springframework/cache/interceptor/CacheAspectSupport\$CacheOperationContext.class
reveals the following.
protected boolean isConditionPassing(java.lang.Object);
Code:
0: aload_0
1: getfield #18 // Field conditionPassing:Ljava/lang/Boolean;
4: ifnonnull 75
7: aload_0
8: getfield #1 // Field metadata:Lorg/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata;
11: invokestatic #13 // Method org/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata.access$300:(Lorg/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata;)Lorg/springframework/cache/interceptor/CacheOperation;
14: invokevirtual #19 // Method org/springframework/cache/interceptor/CacheOperation.getCondition:()Ljava/lang/String;
17: invokestatic #20 // Method org/springframework/util/StringUtils.hasText:(Ljava/lang/String;)Z
20: ifeq 67
23: aload_0
24: aload_1
25: invokespecial #21 // Method createEvaluationContext:(Ljava/lang/Object;)Lorg/springframework/expression/EvaluationContext;
28: astore_2
29: aload_0
30: aload_0
31: getfield #2 // Field this$0:Lorg/springframework/cache/interceptor/CacheAspectSupport;
34: invokestatic #22 // Method org/springframework/cache/interceptor/CacheAspectSupport.access$700:(Lorg/springframework/cache/interceptor/CacheAspectSupport;)Lorg/springframework/cache/interceptor/CacheOperationExpressionEvaluator;
37: aload_0
38: getfield #1 // Field metadata:Lorg/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata;
41: invokestatic #13 // Method org/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata.access$300:(Lorg/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata;)Lorg/springframework/cache/interceptor/CacheOperation;
44: invokevirtual #19 // Method org/springframework/cache/interceptor/CacheOperation.getCondition:()Ljava/lang/String;
47: aload_0
48: getfield #1 // Field metadata:Lorg/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata;
51: invokestatic #23 // Method org/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata.access$600:(Lorg/springframework/cache/interceptor/CacheAspectSupport$CacheOperationMetadata;)Lorg/springframework/context/expression/AnnotatedElementKey;
54: aload_2
55: invokevirtual #24 // Method org/springframework/cache/interceptor/CacheOperationExpressionEvaluator.condition:(Ljava/lang/String;Lorg/springframework/context/expression/AnnotatedElementKey;Lorg/springframework/expression/EvaluationContext;)Z
58: invokestatic #25 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
61: putfield #18 // Field conditionPassing:Ljava/lang/Boolean;
64: goto 75
67: aload_0
68: iconst_1
69: invokestatic #25 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
72: putfield #18 // Field conditionPassing:Ljava/lang/Boolean;
75: aload_0
76: getfield #18 // Field conditionPassing:Ljava/lang/Boolean;
79: invokevirtual #26 // Method java/lang/Boolean.booleanValue:()Z
82: ireturn
We see that auto-boxing occurs for entries 58 and 69 (not just for 69). So if we wanted to make such a change, we'd want to do it in both places.
But we also notice that there's auto-unboxing for entry 79 (the return statement).
In other words, there is actually quite a lot of automatic boxing and unboxing occurring throughout the code base, and we simply let the compiler and JVM optimize as much as possible for us.
In light of that, I am closing this PR.
However, if you determine via benchmarking (e.g., JMH) that this is somehow a hot spot in a normal Spring application, we might consider making a change.
Comment From: chenqimiao
Thank you for your reply. @sbrannen
Actually I am still a bit confused, we know that sometimes auto-boxing or auto-unboxing improve the convenience of program writing, but if it doesn’t work, why don't we minimize this conversion as much as possible? At least a little performance improvement.
Comment From: sbrannen
but if it doesn’t work,
What do you mean by "it doesn't work" in the context of the proposed change?
why don't we minimize this conversion as much as possible? At least a little performance improvement.
We generally don't like to optimize simply for the sake of optimization. Rather, we like to optimize if we know there is a significant improvement for a majority of use cases of the code in question (based on reliable benchmarks).
For the boolean boxing and unboxing involved here, the implementations are already streamlined. See the implementations of Boolean.valueOf(boolean)
and Boolean.booleanValue()
in the JDK for reference. No new objects are being created here: we are effectively always using the Boolean.TRUE
and Boolean.FALSE
singleton constants.
So, although there may be some small performance improvement associated with avoiding the boxing and unboxing as much as possible, the improvement is likely negligible in the grand scheme of things.
Comment From: chenqimiao
but if it doesn’t work,
I mean is that the use of auto-boxing here does not simplify code writing.
But now, I also understand what you mean, we should optimize based on benchmarks, not for optimization.
Thanks again for your reply.
@sbrannen