Reduce ConfigurationPropertyName GC pressure

Rewrite `ConfigurationPropertyName` in an attempt to consume less memory
and to reduce GC pressure from `toString()`.

Prior to this commit the `toString()` method would always construct a
new value from the name elements. This is sub-optimal since on on many
occasions the `ConfigurationPropertyName` is created from an already
well-formed String. The updated code now attempts to directly use the
original value for both `toString` and `equals` whenever possible.

Further refinements have also been made to the way that elements are
stored. Rather than a list or objects, we now use arrays that contains
the split points and types. This helps to reduce the amount of memory
required to store the name.

Closes gh-13414
pull/14560/merge
Phillip Webb 6 years ago
parent 0a187675b5
commit d0de4657d4

@ -52,13 +52,11 @@ class ConfigurationPropertySourcesPropertySource
private ConfigurationProperty findConfigurationProperty(String name) { private ConfigurationProperty findConfigurationProperty(String name) {
try { try {
if (ConfigurationPropertyName.isValid(name)) { return findConfigurationProperty(ConfigurationPropertyName.of(name, true));
return findConfigurationProperty(ConfigurationPropertyName.of(name));
}
} }
catch (Exception ex) { catch (Exception ex) {
return null;
} }
return null;
} }
private ConfigurationProperty findConfigurationProperty( private ConfigurationProperty findConfigurationProperty(

@ -234,10 +234,10 @@ public class ConfigurationPropertyNameTests {
} }
@Test @Test
public void adaptWhenElementValueProcessorIsNullShouldThrowException() { public void adaptWhenElementValueProcessorIsNullShouldAdapt() {
this.thrown.expect(IllegalArgumentException.class); ConfigurationPropertyName name = ConfigurationPropertyName.adapt("foo", '.',
this.thrown.expectMessage("ElementValueProcessor must not be null"); null);
ConfigurationPropertyName.adapt("foo", '.', null); assertThat(name.toString()).isEqualTo("foo");
} }
@Test @Test
@ -304,6 +304,12 @@ public class ConfigurationPropertyNameTests {
assertThat(name.getNumberOfElements()).isEqualTo(3); assertThat(name.getNumberOfElements()).isEqualTo(3);
} }
@Test
public void adaptUnderscoreShouldReturnEmpty() {
assertThat(ConfigurationPropertyName.adapt("_", '_').isEmpty()).isTrue();
assertThat(ConfigurationPropertyName.adapt("_", '.').isEmpty()).isTrue();
}
@Test @Test
public void isEmptyWhenEmptyShouldReturnTrue() { public void isEmptyWhenEmptyShouldReturnTrue() {
assertThat(ConfigurationPropertyName.of("").isEmpty()).isTrue(); assertThat(ConfigurationPropertyName.of("").isEmpty()).isTrue();
@ -538,6 +544,15 @@ public class ConfigurationPropertyNameTests {
"foo.bar", "foo.bard", "foo.baz"); "foo.bar", "foo.bard", "foo.baz");
} }
@Test
public void compareDifferentLengthsShouldSortNames() {
ConfigurationPropertyName name = ConfigurationPropertyName
.of("spring.resources.chain.strategy.content");
ConfigurationPropertyName other = ConfigurationPropertyName
.of("spring.resources.chain.strategy.content.enabled");
assertThat(name.compareTo(other)).isLessThan(0);
}
@Test @Test
public void toStringShouldBeLowerCaseDashed() { public void toStringShouldBeLowerCaseDashed() {
ConfigurationPropertyName name = ConfigurationPropertyName.adapt("fOO.b_-a-r", ConfigurationPropertyName name = ConfigurationPropertyName.adapt("fOO.b_-a-r",
@ -545,6 +560,12 @@ public class ConfigurationPropertyNameTests {
assertThat(name.toString()).isEqualTo("foo.b-a-r"); assertThat(name.toString()).isEqualTo("foo.b-a-r");
} }
@Test
public void toStringFromOfShouldBeLowerCaseDashed() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo.bar-baz");
assertThat(name.toString()).isEqualTo("foo.bar-baz");
}
@Test @Test
public void equalsAndHashCode() { public void equalsAndHashCode() {
ConfigurationPropertyName n01 = ConfigurationPropertyName.of("foo[bar]"); ConfigurationPropertyName n01 = ConfigurationPropertyName.of("foo[bar]");

@ -104,6 +104,19 @@ public class SpringConfigurationPropertySourcesTests {
assertThat(iterator.hasNext()).isFalse(); assertThat(iterator.hasNext()).isFalse();
} }
@Test
public void shouldAdaptSystemEnvironmentPropertySourceWithUnderscoreValue() {
MutablePropertySources sources = new MutablePropertySources();
sources.addLast(new SystemEnvironmentPropertySource(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
Collections.singletonMap("_", "1234")));
Iterator<ConfigurationPropertySource> iterator = new SpringConfigurationPropertySources(
sources).iterator();
ConfigurationPropertyName name = ConfigurationPropertyName.of("bar");
assertThat(iterator.next().getConfigurationProperty(name)).isNull();
assertThat(iterator.hasNext()).isFalse();
}
@Test @Test
public void shouldAdaptMultiplePropertySources() { public void shouldAdaptMultiplePropertySources() {
MutablePropertySources sources = new MutablePropertySources(); MutablePropertySources sources = new MutablePropertySources();

Loading…
Cancel
Save