Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6526574

JMXMP Connector 10 times slower with JAVA 1.4.2 for Map attributes

XMLWordPrintable

      FULL PRODUCT VERSION :
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_12-b03)
      Java HotSpot(TM) Client VM (build 1.4.2_12-b03, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      The JMXMP connector appears to be 10 times slower when retrieving an attribute of type Map underlying certain circumstances:
      1. The JMX server and the JMX client are on different machines
      2. Java 1.4.2 is used to run the JMX server
      3. JMXMP is used. Works fine with the RMI connector
      4. Works the same with Linux on server or client side
      4. The map size is between two bounds (dependent on the size of its content)

      Notes:
      1. Reproducable under Linux, with other JVM (BEA Rockit 1.4.2) and other JMX implementation (MX4J). The JMXMP connector is the only part that can be faulty.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Run server.bat (or convert it to a shell script)
      2. Set the server JMX URL in the client.bat
      3. Run client.bat (or convert it to a shell script)
      4. Look at the result

      The code attached demonstrates this issue very clearly, and it's really not easy to isolate the issue as I've tested the serialization of the map objects and it works fine.

      The behaviour becomes very odd when the size of the map changes, we can clearly see that at a certain point the JMX connector IS 10 times slower.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The JMXMP connector should perform the same under any circumstances for any type of attributes.
      ACTUAL -
      The JMXMP connector will be 10 times slower than normal when the Map size is between 6 and 42. This is screwing our application performance.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      You will find below:
      - 4 Java Files
      - 2 bat files to start the server and the client

      It requires: JRE 1.4.2, jmxri.jar, jmxremote.jar, jmxremote_optional.jar
      A zip file can be sent on demand with everything ready and compiled

      --------------------------------------------------------------------

      File TestServer.java

      package com.test;

      import javax.management.MBeanServer;
      import javax.management.MBeanServerFactory;
      import javax.management.ObjectName;
      import javax.management.remote.JMXConnectorServer;
      import javax.management.remote.JMXConnectorServerFactory;
      import javax.management.remote.JMXServiceURL;

      public class TestServer {
        public static void main(String[] args) {
          try {
            if (args.length != 1) {
              System.out.println("Usage: TestServer <JMX Service URL>");
              return;
            }
            
            // Create connector server
            MBeanServer server = MBeanServerFactory.newMBeanServer();
            JMXServiceURL mServiceURL = new JMXServiceURL(args[0]);
            JMXConnectorServer mConnectorServer = JMXConnectorServerFactory
                .newJMXConnectorServer(mServiceURL, null, server);
            mConnectorServer.start();
            System.out.println("MBeanServerMain.main() on url "
                + mConnectorServer.getAddress());

            // Register Standard MBean
            Test test = new Test();
            ObjectName name = new ObjectName("domain:type=test");
            server.registerMBean(test, name);
            System.out.println("Object Test registered on:" + name);
          } catch (Throwable e) {
            e.printStackTrace();
          }
        }
      }

      -------------------------------------------------------------------------------------
      File TestClient.java:

      package com.test;

      import java.util.Map;

      import javax.management.MBeanServerConnection;
      import javax.management.MBeanServerInvocationHandler;
      import javax.management.ObjectName;
      import javax.management.remote.JMXConnector;
      import javax.management.remote.JMXConnectorFactory;
      import javax.management.remote.JMXServiceURL;

      public class TestClient {
        public static void main(String[] args) {
          if (args.length != 1) {
            System.out.println("Usage: TestClient <JMX Service URL>");
            return;
          }
          
          try {
            // Create connector client
            JMXServiceURL serviceUrl = new JMXServiceURL(args[0]);
            JMXConnector connector = JMXConnectorFactory.connect(serviceUrl, null);
            MBeanServerConnection connection = connector.getMBeanServerConnection();
            System.out.println("Connected on url: " + serviceUrl.toString());

            // Get proxy object
            ObjectName name = new ObjectName("domain:type=test");
            TestMBean mbean = (TestMBean) MBeanServerInvocationHandler
                .newProxyInstance(connection, name, TestMBean.class, true);

            // Init object
            mbean.init();

            // Iterate till the map has no properties left
            int remainingSize;

            do {
              testGetProps(10, mbean);
              remainingSize = mbean.decreaseSize();
            } while (remainingSize > 0);
          } catch (Throwable e) {
            e.printStackTrace();
          }
        }

        private static void testGetProps(int iterations, TestMBean proxy)
            throws Exception {
          long start = System.currentTimeMillis();
          Map result = null;

          for (int i = 0; i < 10; i++) {
            result = proxy.getProps();
          }

          System.out.println("---------------------------------");
          System.out.println("Map size: " + result.size()
              + "\ttestGetPropsTime duration: " + (System.currentTimeMillis() - start)
              + "ms");
        }
      }


      --------------------------------------------------------------------------

      File Test.java

      package com.test;

      import java.util.HashMap;
      import java.util.Map;
      import java.util.Set;

      public class Test implements TestMBean {
        private Map map;

        public Test() throws Exception {
          this.map = buildMap();
        }

        public Map getProps() {
          return map;
        }

        public int decreaseSize() {
          Set keySet = map.keySet();

          if (keySet.size() > 0) {
            map.remove(keySet.iterator().next());
          }

          return map.size();
        }

        public void init() {
          map = buildMap();
        }

        private static Map buildMap() {
          Map props = new HashMap();

          for (int i = 0; i < 64; i++) {
            props.put(i + "keykeykeykeykeykey", "Value " + i);

          }

          return props;
        }
      }


      ------------------------------------------------------------------------------

      File TestMBean.java



      package com.test;

      import java.util.Map;

      public interface TestMBean {
        /**
         * @return The map of this object.
         * @throws Exception
         */
        Map getProps();

        /**
         * Remove an entry in the object map
         *
         * @return The size of the map after having removing the entry
         */
        int decreaseSize();

        /**
         * Restore the map to its initial content
         *
         * @throws Exception
         */
        void init();
      }



      -------------------------------------------------------------------------------------

      File server.bat:

      set CP=test.jar;jmxri.jar;jmxremote.jar;jmxremote_optional.jar
      java -cp %CP% com.test.TestServer service:jmx:jmxmp://localhost:9010
      pause;

      ----------------------------------------------------------------------------------------
      File client.bat

      set CP=test.jar;jmxri.jar;jmxremote.jar;jmxremote_optional.jar

      REM Modify the URL to specify your remote host. The issue only occurs when a remote host is used
      java -cp %CP% com.test.TestClient service:jmx:jmxmp://localhost:9010
      pause;





      ---------- END SOURCE ----------

            sjiang Shanliang Jiang (Inactive)
            emcmanus Eamonn McManus
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: