谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

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のパフォーマンス

続いて、VMに対するJMX接続を行う際のパフォーマンス。


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


現場からは以上です。