spring-boot version: 3.0.2 (since 2.3.0)

In commit 7afd25fc9a30e4e439791504eb8105acfde1d0cc, a cache was introduced to optimize the overhead caused by copying and deduplication of getPropertyNames objects.

But currently we have encountered some problems related to memory pressure. In the process of following the call stack, we found that the cache created in SpringIterableConfigurationPropertySource only exists in two states: 1. Never expires 2. Refresh forever

This is because there is no configuration in the SpringIterableConfigurationPropertySource, and there is no way to configure it (programmatic API or configuration file).

Comment From: philwebb

Are you able to provide some more details about the problems you're facing? Do you have very large property sources or is there some other reason why the memory pressure happens? Perhaps you can share a sample application that replicates the problem.

The cache states are currently set based on if the property source is immutable. The assumption being that if the property source can't change, it's not a problem to keep the cache.

...there is no way to configure it (programmatic API or configuration file

Have you seen the ConfigurationPropertyCaching interface? You should be able to do something like this to configure things:

ConfigurationPropertyCaching.get(sources, propertySource).setTimeToLive(timeToLive);

Comment From: jizhuozhi

Hello, @philwebb . Thanks for your reply :)

The actual usage scenario is a rules engine that relies on several keys in dynamic configuration, here is an example

        String[] keys = new String[]{ "foo", "bar", "foobar" /* other elements... */};
        String[] values = Arrays.stream(keys).map(environment::getProperty).toArray(String[]::new);
        /* do something with values... */

Different rules consume different keys. The complete data collection contains tens of thousands of keys and has a high QPS.

At the same time, unfortunately, we are using G1's immature JDK version, and due to enterprise restrictions, we cannot upgrade it. Therefore, the young generation garbage collection algorithm is still Parallel New.

Have you seen the ConfigurationPropertyCaching interface? You should be able to do something like this to configure things:

I did browse a lot of classes before this, but I paid too much attention to the SpringIterableConfigurationPropertySource class itself, which is package-private, but did not find the content related to ConfigurationPropertyCaching, which really solved my problem, but due to the lack of corresponding documents ( Including javadoc and various search engines) to introduce this way, I think other users may also encounter the same problem.

Just a suggestion, would it be very valuable to provide a user-accessible documentation.

Comment From: jizhuozhi

Hello, @philwebb .

There is still one point that I want to confirm: whether caching should be enabled by default.

In the projects I have been in contact with, and many blogs have mentioned that properties can be obtained programmatically through Environment#getProperty. Unfortunately, no one has ever mentioned that you need to configure the cache yourself. Everyone has made an assumption: after getting the latest snapshot from the configuration server, we can get properties in O(1) as a hash table.

If this values can be cached by default (even if it is only 50ms, P99 of latency in our pure calculation scenario), it will also be greatly improved in the above scenario of cyclically obtaining values.

Comment From: wilkinsona

We've discussed this today. Our feeling is that having 10s of thousands of properties is a fairly extreme edge case. We're also reluctant to enable caching by default as it will cause unexpected and hard to diagnose behavior when a mutable property source changes.

We'll update the reference documentation to make a brief mention of the ConfigurationPropertyCaching interface.