JMXで情報を取得する時のベンチマーク
JMHを使って、JMX経由でMBeanの情報を取る際のパフォーマンスを測定してみた。
ベンチマークのソースコードはこちら。
https://github.com/cero-t/Benchmarks/blob/master/src/main/java/ninja/cero/benchmark/JmxBenchmark.java
ベンチマーク環境はMacBook Pro Late 2013 (Core i5 2.4GHz) で、
他のアプリなども立ち上げっぱなしの環境なのでノイズは多めでだけど、
傾向を見たいだけなのであまり気にせず。
VirtualMachine.attachのパフォーマンス
VMにオンデマンドアタッチする際のパフォーマンス。
No1 : VirtualMachine.attacheしてからシステムプロパティを取ってdetachする
No2 : キャッシュしていたVirtualMachineを使ってシステムプロパティを取得する
@Benchmark public void no1_vmAttach() throws Exception { VirtualMachine vm = VirtualMachine.attach(PID); vm.getSystemProperties(); vm.detach(); } @Benchmark public void no2_vmCachedGetProperties() throws Exception { vm.getSystemProperties(); }
結果
Benchmark | Mode | Cnt | Score | Error | Units |
---|---|---|---|---|---|
JmxBenchmark.no1_vmAttach | thrpt | 10 | 653.834 | ± 108.790 | ops/s |
JmxBenchmark.no2_vmCachedGetProperties | thrpt | 10 | 2330.529 | ± 270.268 | ops/s |
アタッチありは1.5msec程度、キャッシュした場合は0.4msec程度。
ということで、アタッチに掛かる時間は1msec程度と推定。割とでかい。
JMXConnectorFactory.connectのパフォーマンス
No3 : JMXConnectorの取得処理と、クローズ処理をする
No4 : キャッシュしていたJMXConnectorを使って、MBeanServerConnectionの取得とMbean情報を取得する
public JMXConnector no3_vmCachedGetConnector() throws Exception { String connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); if (connectorAddress == null) { String agent = vm.getSystemProperties().getProperty("java.home") + File.separator + "lib" + File.separator + "management-agent.jar"; vm.loadAgent(agent); connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); } JMXServiceURL serviceURL = new JMXServiceURL(connectorAddress); JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL); jmxConnector.close(); } @Benchmark public void no4_connectorCachedGetMBeanCount() throws Exception { MBeanServerConnection connection = connector.getMBeanServerConnection(); connection.getMBeanCount(); }
結果
Benchmark | Mode | Cnt | Score | Error | Units |
---|---|---|---|---|---|
JmxBenchmark.no3_vmCachedGetConnector | thrpt | 10 | 612.652 | ± 95.547 | ops/s |
JmxBenchmark.no4_connectorCachedGetMBeanCount | thrpt | 10 | 9047.803 | ± 1480.741 | ops/s |
JMXの接続と切断は1.6msec程度。おおまかVMに対するアタッチと同じぐらい。
接続したあとの、MBeanServerへの接続とMBean情報取得は0.1msecぐらいで、これは無視できる小さい。
ThreadMXBeanからThreadCountを取るパフォーマンス
今回の主目的はこれ。
ThreadMXBeanを使って情報を取るのと、
MBeanServerConnection.getAttributeで名前を指定して情報を取るのと、どっちが早いか。
No5 : MBeanServerConnection.getAttributeの名前指定でThreadCountを取得する
No6 : ThreadMXBeanを取得してから、getThreadCountで取得する
No7 : キャッシュしていたThreadMXBeanから、getThreadCountで取得する
@Benchmark public void no5_connectorCachedThreadCount() throws Exception { MBeanServerConnection connection = connector.getMBeanServerConnection(); Object count = connection.getAttribute(new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME), "ThreadCount"); sum += (Integer) count; } @Benchmark public void no6_connectorCachedGetThreadCount() throws Exception { MBeanServerConnection connection = connector.getMBeanServerConnection(); ThreadMXBean threadBean = ManagementFactory.newPlatformMXBeanProxy( connection, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class); sum += threadBean.getThreadCount(); } @Benchmark public void no7_beanCachedGetThreadCount() throws Exception { sum += threadMXBean.getThreadCount(); }
結果
Benchmark | Mode | Cnt | Score | Error | Units |
---|---|---|---|---|---|
JmxBenchmark.no5_connectorCachedThreadCount | thrpt | 10 | 8199.887 | ± 1269.164 | ops/s |
JmxBenchmark.no6_connectorCachedGetThreadCount | thrpt | 10 | 2662.147 | ± 585.627 | ops/s |
JmxBenchmark.no7_beanCachedGetThreadCount | thrpt | 10 | 8148.967 | ± 1705.518 | ops/s |
ThreadMXBeanを毎回取る(No6)は明らかにパフォーマンスが悪いけど、
ThreadMXBeanをキャッシュしている限りは、ThreadMXBeanから情報を取るのと、
MBeanServerConnection.getAttributeで取ることに性能差はなし。
まとめ
1. VirtualMachineへのattach/detachは時間が掛かるので、キャッシュすべき
2. JMX接続の確立/切断は時間が掛かるので、キャッシュすべき
3. MBeanServerへの接続は時間が掛からないので、無理にキャッシュしなくてよい(close処理もないのでリソース管理もしてない?)
4. MBeanServerConnection.getAttributeでもThreadMXBeanを使っても性能差はないので、ThreadMXBeanを無理にキャッシュしなくてよい
ベンチマークのソースコード。
https://github.com/cero-t/Benchmarks/blob/master/src/main/java/ninja/cero/benchmark/JmxBenchmark.java
現場からは以上です。