Skip to content

Commit 93113a4

Browse files
committed
Improve performance by not checking all indexed elements
Update `IndexedElementsBinder` so that bind operations are faster at the expense of not checking that all elements have been bound. The updated code now uses a window of 10 elements and assumes that if no elements are missing from that window then exhaustive checking is not required. Closes gh-44867
1 parent 9c25b69 commit 93113a4

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/IndexedElementsBinder.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,7 +43,13 @@
4343
*/
4444
abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
4545

46-
private static final String INDEX_ZERO = "[0]";
46+
private static final String[] INDEXES;
47+
static {
48+
INDEXES = new String[10];
49+
for (int i = 0; i < INDEXES.length; i++) {
50+
INDEXES[i] = "[" + i + "]";
51+
}
52+
}
4753

4854
IndexedElementsBinder(Context context) {
4955
super(context);
@@ -100,15 +106,36 @@ private void bindValue(Bindable<?> target, Collection<Object> collection, Resolv
100106

101107
private void bindIndexed(ConfigurationPropertySource source, ConfigurationPropertyName root,
102108
AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType elementType) {
103-
MultiValueMap<String, ConfigurationPropertyName> knownIndexedChildren = getKnownIndexedChildren(source, root);
109+
int firstUnboundIndex = 0;
110+
boolean hasBindingGap = false;
104111
for (int i = 0; i < Integer.MAX_VALUE; i++) {
105-
ConfigurationPropertyName name = root.append((i != 0) ? "[" + i + "]" : INDEX_ZERO);
112+
ConfigurationPropertyName name = appendIndex(root, i);
106113
Object value = elementBinder.bind(name, Bindable.of(elementType), source);
107-
if (value == null) {
114+
if (value != null) {
115+
collection.get().add(value);
116+
hasBindingGap = hasBindingGap || firstUnboundIndex > 0;
117+
continue;
118+
}
119+
firstUnboundIndex = (firstUnboundIndex <= 0) ? i : firstUnboundIndex;
120+
if (i - firstUnboundIndex > 10) {
108121
break;
109122
}
123+
}
124+
if (hasBindingGap) {
125+
assertNoUnboundChildren(source, root, firstUnboundIndex);
126+
}
127+
}
128+
129+
private ConfigurationPropertyName appendIndex(ConfigurationPropertyName root, int i) {
130+
return root.append((i < INDEXES.length) ? INDEXES[i] : "[" + i + "]");
131+
}
132+
133+
private void assertNoUnboundChildren(ConfigurationPropertySource source, ConfigurationPropertyName root,
134+
int firstUnboundIndex) {
135+
MultiValueMap<String, ConfigurationPropertyName> knownIndexedChildren = getKnownIndexedChildren(source, root);
136+
for (int i = 0; i < firstUnboundIndex; i++) {
137+
ConfigurationPropertyName name = appendIndex(root, i);
110138
knownIndexedChildren.remove(name.getLastElement(Form.UNIFORM));
111-
collection.get().add(value);
112139
}
113140
assertNoUnboundChildren(source, knownIndexedChildren);
114141
}

0 commit comments

Comments
 (0)