Skip to content

Commit 0da7a78

Browse files
authored
SOLR-17340: /admin/info/system optimization by caching BeanInfo (#2538)
Note the prefix arg was always null, thus this one-line change is just a refactoring for correctness.
1 parent a439ebf commit 0da7a78

File tree

2 files changed

+47
-27
lines changed

2 files changed

+47
-27
lines changed

solr/CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ Optimizations
173173

174174
* SOLR-17349: SolrDocumentFetcher should always skip lazy field loading overhead if documentCache==null (Michael Gibney)
175175

176+
* SOLR-17340: Add cache on top of system metrics BeanInfos to make calls to /admin/info/system faster (Pierre Salagnac)
177+
176178
Bug Fixes
177179
---------------------
178180
* SOLR-12813: subqueries should respect basic auth. (Rudy Seitz via Eric Pugh)

solr/core/src/java/org/apache/solr/util/stats/MetricUtils.java

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import java.util.List;
4141
import java.util.Map;
4242
import java.util.SortedSet;
43+
import java.util.concurrent.ConcurrentHashMap;
44+
import java.util.concurrent.ConcurrentMap;
4345
import java.util.concurrent.ExecutorService;
4446
import java.util.concurrent.TimeUnit;
4547
import java.util.function.BiConsumer;
@@ -64,30 +66,37 @@ public class MetricUtils {
6466
public static final String VALUE = "value";
6567
public static final String VALUES = "values";
6668

67-
static final String MS = "_ms";
69+
private static final String MS = "_ms";
6870

69-
static final String MIN = "min";
70-
static final String MIN_MS = MIN + MS;
71-
static final String MAX = "max";
72-
static final String MAX_MS = MAX + MS;
73-
static final String MEAN = "mean";
74-
static final String MEAN_MS = MEAN + MS;
75-
static final String MEDIAN = "median";
76-
static final String MEDIAN_MS = MEDIAN + MS;
77-
static final String STDDEV = "stddev";
78-
static final String STDDEV_MS = STDDEV + MS;
79-
static final String SUM = "sum";
80-
static final String P75 = "p75";
81-
static final String P75_MS = P75 + MS;
82-
static final String P95 = "p95";
83-
static final String P95_MS = P95 + MS;
84-
static final String P99 = "p99";
85-
static final String P99_MS = P99 + MS;
86-
static final String P999 = "p999";
87-
static final String P999_MS = P999 + MS;
71+
private static final String MIN = "min";
72+
private static final String MIN_MS = MIN + MS;
73+
private static final String MAX = "max";
74+
private static final String MAX_MS = MAX + MS;
75+
private static final String MEAN = "mean";
76+
private static final String MEAN_MS = MEAN + MS;
77+
private static final String MEDIAN = "median";
78+
private static final String MEDIAN_MS = MEDIAN + MS;
79+
private static final String STDDEV = "stddev";
80+
private static final String STDDEV_MS = STDDEV + MS;
81+
private static final String SUM = "sum";
82+
private static final String P75 = "p75";
83+
private static final String P75_MS = P75 + MS;
84+
private static final String P95 = "p95";
85+
private static final String P95_MS = P95 + MS;
86+
private static final String P99 = "p99";
87+
private static final String P99_MS = P99 + MS;
88+
private static final String P999 = "p999";
89+
private static final String P999_MS = P999 + MS;
8890

8991
public static final Predicate<CharSequence> ALL_PROPERTIES = (name) -> true;
9092

93+
/**
94+
* Local cache for BeanInfo instances that are created to scan for system metrics. List of
95+
* properties is not supposed to change for the JVM lifespan, so we can keep already create
96+
* BeanInfo instance for future calls.
97+
*/
98+
private static final ConcurrentMap<Class<?>, BeanInfo> beanInfos = new ConcurrentHashMap<>();
99+
91100
/**
92101
* Adds metrics from a Timer to a NamedList, using well-known back-compat names.
93102
*
@@ -764,12 +773,21 @@ public static ExecutorService instrumentedExecutorService(
764773
public static <T extends PlatformManagedObject> void addMXBeanMetrics(
765774
T obj, Class<? extends T> intf, String prefix, BiConsumer<String, Metric> consumer) {
766775
if (intf.isInstance(obj)) {
767-
BeanInfo beanInfo;
768-
try {
769-
beanInfo =
770-
Introspector.getBeanInfo(intf, intf.getSuperclass(), Introspector.IGNORE_ALL_BEANINFO);
771-
} catch (IntrospectionException e) {
772-
log.warn("Unable to fetch properties of MXBean {}", obj.getClass().getName());
776+
BeanInfo beanInfo =
777+
beanInfos.computeIfAbsent(
778+
intf,
779+
clazz -> {
780+
try {
781+
return Introspector.getBeanInfo(
782+
clazz, clazz.getSuperclass(), Introspector.IGNORE_ALL_BEANINFO);
783+
784+
} catch (IntrospectionException e) {
785+
log.warn("Unable to fetch properties of MXBean {}", obj.getClass().getName());
786+
return null;
787+
}
788+
});
789+
790+
if (beanInfo == null) {
773791
return;
774792
}
775793
for (final PropertyDescriptor desc : beanInfo.getPropertyDescriptors()) {
@@ -827,7 +845,7 @@ public static <T extends PlatformManagedObject> void addMXBeanMetrics(
827845
try {
828846
final Class<? extends PlatformManagedObject> intf =
829847
Class.forName(clazz).asSubclass(PlatformManagedObject.class);
830-
MetricUtils.addMXBeanMetrics(obj, intf, null, consumer);
848+
MetricUtils.addMXBeanMetrics(obj, intf, prefix, consumer);
831849
} catch (ClassNotFoundException e) {
832850
// ignore
833851
}

0 commit comments

Comments
 (0)