Skip to content

Commit 0d1aa9a

Browse files
authored
Merge pull request #44448 from radcortez/unrecog-allocs
Reduce allocation in matching of unknown properties
2 parents efcd612 + a04c136 commit 0d1aa9a

File tree

3 files changed

+87
-172
lines changed

3 files changed

+87
-172
lines changed

core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import io.smallrye.config.EnvConfigSource;
8181
import io.smallrye.config.ProfileConfigSourceInterceptor;
8282
import io.smallrye.config.PropertiesConfigSource;
83+
import io.smallrye.config.PropertyName;
8384
import io.smallrye.config.SecretKeys;
8485
import io.smallrye.config.SmallRyeConfig;
8586
import io.smallrye.config.SmallRyeConfigBuilder;
@@ -626,35 +627,27 @@ ReadResult run() {
626627
objectsByClass.put(mapping.getKlass(), config.getConfigMapping(mapping.getKlass(), mapping.getPrefix()));
627628
}
628629

629-
// Build Time Values Recording
630-
for (ConfigClass mapping : buildTimeMappings) {
631-
Set<String> mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
632-
for (String property : mappedProperties) {
630+
Set<PropertyName> buildTimeNames = getMappingsNames(buildTimeMappings);
631+
Set<PropertyName> buildTimeRunTimeNames = getMappingsNames(buildTimeRunTimeMappings);
632+
Set<PropertyName> runTimeNames = getMappingsNames(runTimeMappings);
633+
for (String property : allProperties) {
634+
PropertyName name = new PropertyName(property);
635+
if (buildTimeNames.contains(name)) {
633636
unknownBuildProperties.remove(property);
634637
ConfigValue value = config.getConfigValue(property);
635638
if (value.getRawValue() != null) {
636639
allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
637640
}
638641
}
639-
}
640-
641-
// Build Time and Run Time Values Recording
642-
for (ConfigClass mapping : buildTimeRunTimeMappings) {
643-
Set<String> mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
644-
for (String property : mappedProperties) {
642+
if (buildTimeRunTimeNames.contains(name)) {
645643
unknownBuildProperties.remove(property);
646644
ConfigValue value = config.getConfigValue(property);
647645
if (value.getRawValue() != null) {
648646
allBuildTimeValues.put(value.getNameProfiled(), value.getRawValue());
649647
buildTimeRunTimeValues.put(value.getNameProfiled(), value.getRawValue());
650648
}
651649
}
652-
}
653-
654-
// Run Time Values Recording
655-
for (ConfigClass mapping : runTimeMappings) {
656-
Set<String> mappedProperties = ConfigMappings.mappedProperties(mapping, allProperties);
657-
for (String property : mappedProperties) {
650+
if (runTimeNames.contains(name)) {
658651
unknownBuildProperties.remove(property);
659652
ConfigValue value = runtimeConfig.getConfigValue(property);
660653
if (value.getRawValue() != null) {
@@ -1216,6 +1209,14 @@ private static void getDefaults(
12161209
patternMap.getChild(childName));
12171210
}
12181211
}
1212+
1213+
private static Set<PropertyName> getMappingsNames(final List<ConfigClass> configMappings) {
1214+
Set<String> names = new HashSet<>();
1215+
for (ConfigClass configMapping : configMappings) {
1216+
names.addAll(ConfigMappings.getProperties(configMapping).keySet());
1217+
}
1218+
return PropertiesUtil.toPropertyNames(names);
1219+
}
12191220
}
12201221

12211222
public static final class ReadResult {

core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java

Lines changed: 46 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
import io.smallrye.config.ConfigMappings;
6767
import io.smallrye.config.ConfigMappings.ConfigClass;
6868
import io.smallrye.config.Converters;
69-
import io.smallrye.config.KeyMap;
69+
import io.smallrye.config.PropertyName;
7070
import io.smallrye.config.SmallRyeConfig;
7171
import io.smallrye.config.SmallRyeConfigBuilder;
7272

@@ -86,10 +86,13 @@ public final class RunTimeConfigurationGenerator {
8686
public static final MethodDescriptor REINIT = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "reinit",
8787
void.class);
8888
public static final MethodDescriptor C_READ_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "readConfig", void.class);
89+
90+
static final FieldDescriptor C_MAPPED_PROPERTIES = FieldDescriptor.of(CONFIG_CLASS_NAME, "mappedProperties", Set.class);
91+
static final MethodDescriptor C_GENERATE_MAPPED_PROPERTIES = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME,
92+
"generateMappedProperties", Set.class);
93+
static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class);
8994
static final FieldDescriptor C_UNKNOWN = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknown", Set.class);
9095
static final FieldDescriptor C_UNKNOWN_RUNTIME = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknownRuntime", Set.class);
91-
static final MethodDescriptor C_MAPPED_PROPERTIES = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "mappedProperties",
92-
KeyMap.class);
9396

9497
static final MethodDescriptor CD_INVALID_VALUE = MethodDescriptor.ofMethod(ConfigDiagnostic.class, "invalidValue",
9598
void.class, String.class, IllegalArgumentException.class);
@@ -177,23 +180,21 @@ public final class RunTimeConfigurationGenerator {
177180
Object.class, String.class, Converter.class);
178181

179182
static final MethodDescriptor SRCB_NEW = MethodDescriptor.ofConstructor(SmallRyeConfigBuilder.class);
180-
181183
static final MethodDescriptor SRCB_WITH_CONVERTER = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class,
182184
"withConverter", ConfigBuilder.class, Class.class, int.class, Converter.class);
183185
static final MethodDescriptor SRCB_WITH_CUSTOMIZER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
184186
"withCustomizer", void.class, SmallRyeConfigBuilder.class, String.class);
185187
static final MethodDescriptor SRCB_BUILD = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, "build",
186188
SmallRyeConfig.class);
187189

188-
static final MethodDescriptor PU_FILTER_PROPERTIES_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class,
189-
"filterPropertiesInRoots", Iterable.class, Iterable.class, Set.class);
190-
191190
static final MethodDescriptor PU_IS_PROPERTY_QUARKUS_COMPOUND_NAME = MethodDescriptor.ofMethod(PropertiesUtil.class,
192191
"isPropertyQuarkusCompoundName", boolean.class, NameIterator.class);
193-
static final MethodDescriptor PU_FILTER_UNKNOWN = MethodDescriptor.ofMethod(PropertiesUtil.class, "filterUnknown",
194-
void.class, Set.class, KeyMap.class);
192+
static final MethodDescriptor PU_IS_PROPERTY_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class, "isPropertyInRoots",
193+
boolean.class, String.class, Set.class);
195194
static final MethodDescriptor HS_NEW = MethodDescriptor.ofConstructor(HashSet.class);
196195
static final MethodDescriptor HS_ADD = MethodDescriptor.ofMethod(HashSet.class, "add", boolean.class, Object.class);
196+
static final MethodDescriptor HS_CONTAINS = MethodDescriptor.ofMethod(HashSet.class, "contains", boolean.class,
197+
Object.class);
197198

198199
// todo: more space-efficient sorted map impl
199200
static final MethodDescriptor TM_NEW = MethodDescriptor.ofConstructor(TreeMap.class);
@@ -261,8 +262,8 @@ public static final class GenerateOperation implements AutoCloseable {
261262
roots = Assert.checkNotNullParam("builder.roots", builder.getBuildTimeReadResult().getAllRoots());
262263
additionalTypes = Assert.checkNotNullParam("additionalTypes", builder.getAdditionalTypes());
263264
cc = ClassCreator.builder().classOutput(classOutput).className(CONFIG_CLASS_NAME).setFinal(true).build();
265+
generateMappedProperties();
264266
generateEmptyParsers();
265-
generateUnknownFilter();
266267
// not instantiable
267268
try (MethodCreator mc = cc.getMethodCreator(MethodDescriptor.ofConstructor(CONFIG_CLASS_NAME))) {
268269
mc.setModifiers(Opcodes.ACC_PRIVATE);
@@ -280,10 +281,13 @@ public static final class GenerateOperation implements AutoCloseable {
280281
clinit = cc.getMethodCreator(MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "<clinit>", void.class));
281282
clinit.setModifiers(Opcodes.ACC_STATIC);
282283

283-
cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL);
284+
cc.getFieldCreator(C_MAPPED_PROPERTIES).setModifiers(Opcodes.ACC_STATIC);
285+
clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.invokeStaticMethod(C_GENERATE_MAPPED_PROPERTIES));
286+
287+
cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC);
284288
clinit.writeStaticField(C_UNKNOWN, clinit.newInstance(HS_NEW));
285289

286-
cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL);
290+
cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC);
287291
clinit.writeStaticField(C_UNKNOWN_RUNTIME, clinit.newInstance(HS_NEW));
288292

289293
clinitNameBuilder = clinit.newInstance(SB_NEW);
@@ -457,21 +461,13 @@ public void run() {
457461

458462
// generate sweep for clinit
459463
configSweepLoop(siParserBody, clinit, clinitConfig, getRegisteredRoots(BUILD_AND_RUN_TIME_FIXED), Type.BUILD_TIME);
460-
461-
clinit.invokeStaticMethod(PU_FILTER_UNKNOWN,
462-
clinit.readStaticField(C_UNKNOWN),
463-
clinit.invokeStaticMethod(C_MAPPED_PROPERTIES));
464464
clinit.invokeStaticMethod(CD_UNKNOWN_PROPERTIES, clinit.readStaticField(C_UNKNOWN));
465465

466466
if (liveReloadPossible) {
467467
configSweepLoop(siParserBody, readConfig, runTimeConfig, getRegisteredRoots(RUN_TIME), Type.RUNTIME);
468468
}
469469
// generate sweep for run time
470470
configSweepLoop(rtParserBody, readConfig, runTimeConfig, getRegisteredRoots(RUN_TIME), Type.RUNTIME);
471-
472-
readConfig.invokeStaticMethod(PU_FILTER_UNKNOWN,
473-
readConfig.readStaticField(C_UNKNOWN_RUNTIME),
474-
readConfig.invokeStaticMethod(C_MAPPED_PROPERTIES));
475471
readConfig.invokeStaticMethod(CD_UNKNOWN_PROPERTIES_RT, readConfig.readStaticField(C_UNKNOWN_RUNTIME));
476472

477473
// generate ensure-initialized method
@@ -525,33 +521,42 @@ public void run() {
525521

526522
private void configSweepLoop(MethodDescriptor parserBody, MethodCreator method, ResultHandle config,
527523
Set<String> registeredRoots, Type type) {
528-
ResultHandle nameSet;
529-
ResultHandle iterator;
524+
ResultHandle propertyNames = method.invokeVirtualMethod(SRC_GET_PROPERTY_NAMES, config);
525+
ResultHandle iterator = method.invokeInterfaceMethod(ITRA_ITERATOR, propertyNames);
530526

531-
nameSet = filterProperties(method, config, registeredRoots);
532-
iterator = method.invokeInterfaceMethod(ITRA_ITERATOR, nameSet);
527+
ResultHandle rootSet = method.newInstance(HS_NEW);
528+
for (String registeredRoot : registeredRoots) {
529+
method.invokeVirtualMethod(HS_ADD, rootSet, method.load(registeredRoot));
530+
}
533531

534532
try (BytecodeCreator sweepLoop = method.createScope()) {
535533
try (BytecodeCreator hasNext = sweepLoop.ifNonZero(sweepLoop.invokeInterfaceMethod(ITR_HAS_NEXT, iterator))
536534
.trueBranch()) {
537-
538535
ResultHandle key = hasNext.checkCast(hasNext.invokeInterfaceMethod(ITR_NEXT, iterator), String.class);
536+
537+
// !mappedProperties.contains(new PropertyName(key)) continue sweepLoop;
538+
hasNext.ifNonZero(
539+
hasNext.invokeVirtualMethod(HS_CONTAINS, hasNext.readStaticField(C_MAPPED_PROPERTIES),
540+
hasNext.newInstance(PN_NEW, key)))
541+
.trueBranch().continueScope(sweepLoop);
542+
539543
// NameIterator keyIter = new NameIterator(key);
540544
ResultHandle keyIter = hasNext.newInstance(NI_NEW_STRING, key);
541-
BranchResult unknownProperty = hasNext
545+
546+
// if (PropertiesUtil.isPropertyQuarkusCompoundName(keyIter))
547+
BranchResult quarkusCompoundName = hasNext
542548
.ifNonZero(hasNext.invokeStaticMethod(PU_IS_PROPERTY_QUARKUS_COMPOUND_NAME, keyIter));
543-
try (BytecodeCreator trueBranch = unknownProperty.trueBranch()) {
544-
ResultHandle unknown;
545-
if (type == Type.BUILD_TIME) {
546-
unknown = trueBranch.readStaticField(C_UNKNOWN);
547-
} else {
548-
unknown = trueBranch.readStaticField(C_UNKNOWN_RUNTIME);
549-
}
549+
try (BytecodeCreator trueBranch = quarkusCompoundName.trueBranch()) {
550+
ResultHandle unknown = type == Type.BUILD_TIME ? trueBranch.readStaticField(C_UNKNOWN)
551+
: trueBranch.readStaticField(C_UNKNOWN_RUNTIME);
550552
trueBranch.invokeVirtualMethod(HS_ADD, unknown, key);
551553
}
554+
555+
hasNext.ifNonZero(hasNext.invokeStaticMethod(PU_IS_PROPERTY_IN_ROOTS, key, rootSet)).falseBranch()
556+
.continueScope(sweepLoop);
557+
552558
// if (! keyIter.hasNext()) continue sweepLoop;
553559
hasNext.ifNonZero(hasNext.invokeVirtualMethod(NI_HAS_NEXT, keyIter)).falseBranch().continueScope(sweepLoop);
554-
// if (! keyIter.nextSegmentEquals("quarkus")) continue sweepLoop;
555560
// parse(config, keyIter);
556561
hasNext.invokeStaticMethod(parserBody, config, keyIter);
557562
// continue sweepLoop;
@@ -560,21 +565,6 @@ private void configSweepLoop(MethodDescriptor parserBody, MethodCreator method,
560565
}
561566
}
562567

563-
private ResultHandle filterProperties(MethodCreator method, ResultHandle config, Set<String> registeredRoots) {
564-
// Roots
565-
ResultHandle rootSet;
566-
rootSet = method.newInstance(HS_NEW);
567-
for (String registeredRoot : registeredRoots) {
568-
method.invokeVirtualMethod(HS_ADD, rootSet, method.load(registeredRoot));
569-
}
570-
571-
// PropertyNames
572-
ResultHandle properties = method.invokeVirtualMethod(SRC_GET_PROPERTY_NAMES, config);
573-
574-
// Filtered Properties
575-
return method.invokeStaticMethod(PU_FILTER_PROPERTIES_IN_ROOTS, properties, rootSet);
576-
}
577-
578568
private Set<String> getRegisteredRoots(ConfigPhase configPhase) {
579569
Set<String> registeredRoots = new HashSet<>();
580570
for (RootDefinition root : roots) {
@@ -1200,13 +1190,7 @@ private FieldDescriptor getOrCreateConverterInstance(Field field, ConverterType
12001190
return fd;
12011191
}
12021192

1203-
static final MethodDescriptor KM_NEW = MethodDescriptor.ofConstructor(KeyMap.class);
1204-
static final MethodDescriptor KM_FIND_OR_ADD = MethodDescriptor.ofMethod(KeyMap.class, "findOrAdd", KeyMap.class,
1205-
String.class);
1206-
static final MethodDescriptor KM_PUT_ROOT_VALUE = MethodDescriptor.ofMethod(KeyMap.class, "putRootValue", Object.class,
1207-
Object.class);
1208-
1209-
private void generateUnknownFilter() {
1193+
private void generateMappedProperties() {
12101194
Set<String> names = new HashSet<>();
12111195
for (ConfigClass buildTimeMapping : buildTimeConfigResult.getBuildTimeMappings()) {
12121196
names.addAll(ConfigMappings.getProperties(buildTimeMapping).keySet());
@@ -1217,17 +1201,15 @@ private void generateUnknownFilter() {
12171201
for (ConfigClass runtimeConfigMapping : buildTimeConfigResult.getRunTimeMappings()) {
12181202
names.addAll(ConfigMappings.getProperties(runtimeConfigMapping).keySet());
12191203
}
1204+
Set<PropertyName> propertyNames = PropertiesUtil.toPropertyNames(names);
12201205

1221-
// Add a method that generates a KeyMap that can check if a property is mapped by a @ConfigMapping
1222-
MethodCreator mc = cc.getMethodCreator(C_MAPPED_PROPERTIES);
1206+
MethodCreator mc = cc.getMethodCreator(C_GENERATE_MAPPED_PROPERTIES);
12231207
mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
1224-
ResultHandle keyMap = mc.newInstance(KM_NEW);
1225-
for (String name : names) {
1226-
mc.invokeVirtualMethod(KM_PUT_ROOT_VALUE, mc.invokeVirtualMethod(KM_FIND_OR_ADD, keyMap, mc.load(name)),
1227-
mc.load(true));
1208+
ResultHandle set = mc.newInstance(HS_NEW);
1209+
for (PropertyName propertyName : propertyNames) {
1210+
mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(propertyName.getName())));
12281211
}
1229-
1230-
mc.returnValue(keyMap);
1212+
mc.returnValue(set);
12311213
mc.close();
12321214
}
12331215

0 commit comments

Comments
 (0)