-
Enhancement
-
Resolution: Fixed
-
P4
-
None
-
b11
-
generic
-
generic
JMX queries consume a lot of memory and CPU usage if called with wildcard patterns.
The reason is Repository$ObjectNamePattern.matchKeys():
>> public boolean matchKeys(ObjectName name) {
>> // If key property value pattern but not key property list
>> // pattern, then the number of key properties must be equal
>> //
>> if (isPropertyValuePattern &&
>> !isPropertyListPattern &&
>> (name.getKeyPropertyList().size() != keys.length))
>> return false;
and more specifically name.getKeyPropertyList().
And getKeyPropertyList() looks like this:
>> public Hashtable<String,String> getKeyPropertyList() { return new Hashtable<String,String>(_getKeyPropertyList()); }
So, every call to Repository$ObjectNamePattern.matchKeys() creates a new HashTable and fills it with key properties.
This expensive operation can be omitted by using ObjectName.apply()
The attached test shows 2 times better performance and memory usage.
The test is created on the base of RepositoryWildcardTest jtreg test:
Before:
>> $ java test 1000000 1000000
>> Test PASSED in 8943169791 ns.
>> GC: G1 Young Generation getCollectionCount()=177 getCollectionTime()=118
After:
>> $ java test 1000000 1000000
>> Test PASSED in 4808213917 ns.
>> GC: G1 Young Generation getCollectionCount()=88 getCollectionTime()=53
Benchmark results for original implementation:
Benchmark (N) Mode Cnt Score Error Units
JmxBenchmark.applyForMyObjectName 1000 thrpt 10 539.134 ± 11.643 ops/s
JmxBenchmark.applyForObjectName 1000 thrpt 10 495.961 ± 10.550 ops/s
JmxBenchmark.queryMBeansForMyObjectName 1000 thrpt 10 75.482 ± 0.302 ops/s
JmxBenchmark.queryMBeansForObjectName 1000 thrpt 10 111.721 ± 0.462 ops/s
JmxBenchmark.queryNamesForMyObjectName 1000 thrpt 10 79.004 ± 0.398 ops/s
JmxBenchmark.queryNamesForObjectName 1000 thrpt 10 125.877 ± 2.024 ops/s
Benchmark results for the proposed implementation:
Benchmark (N) Mode Cnt Score Error Units
JmxBenchmark.applyForMyObjectName 1000 thrpt 10 542.233 ± 4.137 ops/s
JmxBenchmark.applyForObjectName 1000 thrpt 10 668.710 ± 13.124 ops/s
JmxBenchmark.queryMBeansForMyObjectName 1000 thrpt 10 123.381 ± 4.254 ops/s
JmxBenchmark.queryMBeansForObjectName 1000 thrpt 10 237.607 ± 3.298 ops/s
JmxBenchmark.queryNamesForMyObjectName 1000 thrpt 10 122.576 ± 2.364 ops/s
JmxBenchmark.queryNamesForObjectName 1000 thrpt 10 238.275 ± 4.904 ops/s
The reason is Repository$ObjectNamePattern.matchKeys():
>> public boolean matchKeys(ObjectName name) {
>> // If key property value pattern but not key property list
>> // pattern, then the number of key properties must be equal
>> //
>> if (isPropertyValuePattern &&
>> !isPropertyListPattern &&
>> (name.getKeyPropertyList().size() != keys.length))
>> return false;
and more specifically name.getKeyPropertyList().
And getKeyPropertyList() looks like this:
>> public Hashtable<String,String> getKeyPropertyList() { return new Hashtable<String,String>(_getKeyPropertyList()); }
So, every call to Repository$ObjectNamePattern.matchKeys() creates a new HashTable and fills it with key properties.
This expensive operation can be omitted by using ObjectName.apply()
The attached test shows 2 times better performance and memory usage.
The test is created on the base of RepositoryWildcardTest jtreg test:
Before:
>> $ java test 1000000 1000000
>> Test PASSED in 8943169791 ns.
>> GC: G1 Young Generation getCollectionCount()=177 getCollectionTime()=118
After:
>> $ java test 1000000 1000000
>> Test PASSED in 4808213917 ns.
>> GC: G1 Young Generation getCollectionCount()=88 getCollectionTime()=53
Benchmark results for original implementation:
Benchmark (N) Mode Cnt Score Error Units
JmxBenchmark.applyForMyObjectName 1000 thrpt 10 539.134 ± 11.643 ops/s
JmxBenchmark.applyForObjectName 1000 thrpt 10 495.961 ± 10.550 ops/s
JmxBenchmark.queryMBeansForMyObjectName 1000 thrpt 10 75.482 ± 0.302 ops/s
JmxBenchmark.queryMBeansForObjectName 1000 thrpt 10 111.721 ± 0.462 ops/s
JmxBenchmark.queryNamesForMyObjectName 1000 thrpt 10 79.004 ± 0.398 ops/s
JmxBenchmark.queryNamesForObjectName 1000 thrpt 10 125.877 ± 2.024 ops/s
Benchmark results for the proposed implementation:
Benchmark (N) Mode Cnt Score Error Units
JmxBenchmark.applyForMyObjectName 1000 thrpt 10 542.233 ± 4.137 ops/s
JmxBenchmark.applyForObjectName 1000 thrpt 10 668.710 ± 13.124 ops/s
JmxBenchmark.queryMBeansForMyObjectName 1000 thrpt 10 123.381 ± 4.254 ops/s
JmxBenchmark.queryMBeansForObjectName 1000 thrpt 10 237.607 ± 3.298 ops/s
JmxBenchmark.queryNamesForMyObjectName 1000 thrpt 10 122.576 ± 2.364 ops/s
JmxBenchmark.queryNamesForObjectName 1000 thrpt 10 238.275 ± 4.904 ops/s
- links to
-
Commit openjdk/jdk/9a797228
-
Review openjdk/jdk11u-dev/1762
-
Review openjdk/jdk/11758
-
Review(master) openjdk/jdk17u-dev/1182