From 5c691960a2129612b905f9dcc0452014a06d14ad Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sat, 26 Aug 2023 17:45:25 +0200 Subject: [PATCH] Polish "Improve performance of CompositePropertySource#getPropertyNames" See gh-27236 --- .../env/CompositePropertySourceBenchmark.java | 18 ++++++++++++------ .../core/env/CompositePropertySource.java | 6 ++---- .../core/env/CompositePropertySourceTests.java | 10 ++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/spring-core/src/jmh/java/org/springframework/core/env/CompositePropertySourceBenchmark.java b/spring-core/src/jmh/java/org/springframework/core/env/CompositePropertySourceBenchmark.java index 73d3d18f52..3d5eae2bdf 100644 --- a/spring-core/src/jmh/java/org/springframework/core/env/CompositePropertySourceBenchmark.java +++ b/spring-core/src/jmh/java/org/springframework/core/env/CompositePropertySourceBenchmark.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang3.RandomStringUtils; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Level; @@ -34,6 +33,9 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import org.springframework.util.AlternativeJdkIdGenerator; +import org.springframework.util.IdGenerator; + /** * Benchmarks for {@link CompositePropertySource}. * @@ -53,14 +55,16 @@ public class CompositePropertySourceBenchmark { @State(Scope.Benchmark) public static class BenchmarkState { - static final Object VALUE = new Object(); + private static final IdGenerator ID_GENERATOR = new AlternativeJdkIdGenerator(); + + private static final Object VALUE = new Object(); CompositePropertySource composite; - @Param({"2", "5", "10"}) + @Param({ "2", "5", "10" }) int numberOfPropertySource; - @Param({"10", "100", "1000"}) + @Param({ "10", "100", "1000" }) int numberOfPropertyNamesPerSource; @Setup(Level.Trial) @@ -69,11 +73,13 @@ public class CompositePropertySourceBenchmark { for (int i = 0; i < this.numberOfPropertySource; i++) { Map map = new HashMap<>(this.numberOfPropertyNamesPerSource); for (int j = 0; j < this.numberOfPropertyNamesPerSource; j++) { - map.put(RandomStringUtils.randomAlphanumeric(5, 50), VALUE); + map.put(ID_GENERATOR.generateId().toString(), VALUE); } PropertySource propertySource = new MapPropertySource("propertySource" + i, map); this.composite.addPropertySource(propertySource); } } + } + } diff --git a/spring-core/src/main/java/org/springframework/core/env/CompositePropertySource.java b/spring-core/src/main/java/org/springframework/core/env/CompositePropertySource.java index efc59f67a9..7345ff4dff 100644 --- a/spring-core/src/main/java/org/springframework/core/env/CompositePropertySource.java +++ b/spring-core/src/main/java/org/springframework/core/env/CompositePropertySource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -90,9 +90,7 @@ public class CompositePropertySource extends EnumerablePropertySource { total += names.length; } Set allNames = new LinkedHashSet<>(total); - for (String[] names : namesList) { - allNames.addAll(Arrays.asList(names)); - } + namesList.forEach(names -> allNames.addAll(Arrays.asList(names))); return StringUtils.toStringArray(allNames); } diff --git a/spring-core/src/test/java/org/springframework/core/env/CompositePropertySourceTests.java b/spring-core/src/test/java/org/springframework/core/env/CompositePropertySourceTests.java index d7bafe3764..fba8bd2aa5 100644 --- a/spring-core/src/test/java/org/springframework/core/env/CompositePropertySourceTests.java +++ b/spring-core/src/test/java/org/springframework/core/env/CompositePropertySourceTests.java @@ -17,6 +17,7 @@ package org.springframework.core.env; import java.util.Collections; +import java.util.Map; import org.junit.jupiter.api.Test; @@ -46,4 +47,13 @@ class CompositePropertySourceTests { assertThat(((i1 < i2) && (i2 < i3))).as("Bad order: " + s).isTrue(); } + @Test + void getPropertyNamesRemovesDuplicates() { + CompositePropertySource composite = new CompositePropertySource("c"); + composite.addPropertySource(new MapPropertySource("p1", Map.of("p1.property", "value"))); + composite.addPropertySource(new MapPropertySource("p2", + Map.of("p2.property1", "value", "p1.property", "value", "p2.property2", "value"))); + assertThat(composite.getPropertyNames()).containsOnly("p1.property", "p2.property1", "p2.property2"); + } + }