Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POOL-393] Improve BaseGenericObjectPool's JMX Register performance #199

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

niallkp
Copy link

@niallkp niallkp commented Dec 22, 2022

The algorithm for generating the JMX name for newly created pools can be very slow if the number of pools is large. This PR makes a 10x improvement without changing the naming sequence.

I tried a couple of approaches - first retrieving all the registered pool names using the MBeanServer's queryNames(ObjectName, QueryExp) method and and then using MBeanServer's isRegistered(ObjectName) method. The later involved many more JMX calls but was slightly faster and simpler code - so this PR uses that approach.

This PR seems to provide the performance improvement without changing behavior - which Phil didn't like in #115

@kinow kinow requested a review from psteitz Dec 22, 2022
@codecov-commenter
Copy link

codecov-commenter commented Dec 22, 2022

Codecov Report

Merging #199 (0ee2597) into master (eb2cf8e) will decrease coverage by 0.11%.
The diff coverage is 100.00%.

@@             Coverage Diff              @@
##             master     #199      +/-   ##
============================================
- Coverage     81.83%   81.71%   -0.12%     
+ Complexity      760      759       -1     
============================================
  Files            42       42              
  Lines          3066     3068       +2     
  Branches        308      309       +1     
============================================
- Hits           2509     2507       -2     
- Misses          450      452       +2     
- Partials        107      109       +2     
Impacted Files Coverage Δ
...ache/commons/pool2/impl/BaseGenericObjectPool.java 88.12% <100.00%> (-0.66%) ⬇️
...g/apache/commons/pool2/impl/GenericObjectPool.java 83.85% <0.00%> (-0.27%) ⬇️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

kinow
kinow approved these changes Dec 22, 2022
Copy link
Member

@kinow kinow left a comment

Code looks OK. Had a look at pool to see if it had JMH tests, but found none. Tagged @psteitz as reviewer as he is mentioned in the issue & changelog 👍

Copy link
Member

@garydgregory garydgregory left a comment

Is there still a possibility of an infinite loop due to retries? Shouldn’t we have a count or time bound on retires?

@niallkp
Copy link
Author

niallkp commented Dec 24, 2022

Sorry Gary, not sure what you mean about retries. When it retries it changes the name by incrementing the count - since the count is appended to the name of the MBean being registered. So I'm not sure how this gets into an infinite loop?

@garydgregory
Copy link
Member

garydgregory commented Dec 24, 2022

What if another thread, somewhere, is also using Pool, also wanting JMX...

@kinow
Copy link
Member

kinow commented Dec 24, 2022

The class docs state it's intended to be thread-safe, and that i variable's scope is limited to the method. It should be fine regarding other threads trying to instantiate it I think.

I think @garydgregory is right asking if it there is a scenario where it just keeps going in a loop trying to register jmxbean, jmxbean1, jmxbean2, ..., jmxbean9999. But I think if that's a possible scenario, that deserves a separate issue as I think that affects master too (or at least deserves a comment in the javadocs or in the code body telling others why that wouldn't happen).

@niallkp
Copy link
Author

niallkp commented Dec 24, 2022

Firstly I would say that this PR doesn't change the logic of the method - it just checks first whether theres already a MBean with the same name rather than trying to register an MBean and having it throw an InstanceAlreadyExistsException and this appears to improve the performance x10 despite all the additional calls to the isRegisterd() method.

On the issue of multiple threads registering multiple pools at the same time, then they will iterate until a free name is found and the only possibility I see for an infinite loop would be if all possible names had already been registered. Its hard to conceive of that being the case and I suspect that other issues would occur in that case (out of memory issues).

So locally I created a test case with two Callable instances which both create 3 thread pools in separate threads and then printed out the JMX Name of each pool and it produced the following results:

First Task:

  • org.apache.commons.pool2:type=GenericObjectPool,name=pool2
  • org.apache.commons.pool2:type=GenericObjectPool,name=pool4
  • org.apache.commons.pool2:type=GenericObjectPool,name=pool6

Second Task:

  • org.apache.commons.pool2:type=GenericObjectPool,name=pool3
  • org.apache.commons.pool2:type=GenericObjectPool,name=pool5
  • org.apache.commons.pool2:type=GenericObjectPool,name=pool7

If you want I can add this test case to the PR?

(Note: the reason there isn't an MBean with name=pool is because TestBaseGenericObjectPool sets up a GenericObjectPool in the setup() method of the test which is already registered)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants