Posts tagged ‘reflection’

Circumventing creating objects via Reflection vs Direct object manipulation

Of course its no secret that reflection is a lot slower than that direct object manipulation but with java 5 and 6 the speed has dramatically improved I wanted to find out just how much of a penalty hit was it to use reflection rather than direct object manipulation to create objects (from the database end for eg.).

The answer is - substantial.

Here is a code that basically populates an object with random data - first completely via reflection and then by using actual java code:

package net.ahlawat.Main;

import java.lang.reflect.Method;
import java.util.*;

public class Main {
    static class TestClass {
        private String firstname;
        private String lastname;
        private String username;
        private String address;
        private String email;

        public String getFirstname() {
            return firstname;
        }

        public void setFirstname(String firstname) {
            this.firstname = firstname;
        }

        public String getLastname() {
            return lastname;
        }

        public void setLastname(String lastname) {
            this.lastname = lastname;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }
    }

    public static void main(String[] args) {
        System.out.println("Reflection performance");

        try {
            long start = System.currentTimeMillis();
            Method[] methods = TestClass.class.getMethods();
            List<Method> objectMethods = Arrays.asList(Object.class.getMethods()); 

            List<Method> setters = new ArrayList<Method>();

            for (Method method : methods) {
                String name = method.getName();
                if (objectMethods.contains(method)) {
                    continue;
                } else if (name.startsWith("set") && method.getParameterTypes().length == 1) {
                    setters.add(method);
                }
            }

            System.out.println(String.format("Resolving all methods in %s ms", (System.currentTimeMillis()-start)));

            int objectCount = 10000;
            Random random = new Random();
            start = System.currentTimeMillis();
            for (int x=0; x<objectCount; x++) {
                Object o = TestClass.class.newInstance();
                for (Method getter : setters) {
                    getter.invoke(o, random.nextDouble() + "");
                }
            }
            long refTime = System.currentTimeMillis() - start;
            System.out.println(String.format(Locale.getDefault(),"Creating %d objects via reflection: %d ms",
                    objectCount, refTime));

            start = System.currentTimeMillis();
            for(int x = 0; x<objectCount; x++) {
                TestClass ob = new TestClass();
                ob.setAddress(random.nextDouble() + "");
                ob.setFirstname(random.nextDouble() + "");
                ob.setLastname(random.nextDouble() + "");
                ob.setUsername(random.nextDouble() + "");
                ob.setEmail(random.nextDouble() + "");
            }

            long directTime = System.currentTimeMillis() - start;
            System.out.println(String.format(Locale.getDefault(),"Creating %d objects via direct object manipulation: %d ms",
                    objectCount, directTime));

            System.out.println(String.format("Slowness: %.2f%%", (double)(refTime-directTime)*100/directTime));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Quite straight forward. Here are the results:

Reflection performance
Resolving all methods in 2 ms
Creating 10000 objects via reflection: 218 ms
Creating 10000 objects via direct object manipulation: 129 ms
Slowness: 68.99%

Oddly internally the compiler optimized the reflective transfer if you do it many times over - I don’t know what exactly causes it but increasing the number to 100,000 instead the slowness is 40%.

Reflection performance
Resolving all methods in 2 ms
Creating 100000 objects via reflection: 1714 ms
Creating 100000 objects via direct object manipulation: 1213 ms
Slowness: 41.30%

If you take a look at just milliseconds it might not seem like a lot - but if you use reflection excessively it will kill the performance of you app. The good thing is you don’t have to live with it.

If you must use reflection due to the dynamic nature of the framework you are putting in place you are much better off writing a one time code generator. Using this generator you can overcome the 50% penalty of using reflection and yet keep the application dynamic.

So use reflection to produce the code that does direct object transfer to a .java file - compile it and use it. I plan to use the same for a data access service object which reads stuff from a table and populates an object using annotations on the class (a hibernate wannabe if you will). The milliseconds will add up pretty fast. I can share the groovy code generator if people are interested.