Showing posts with label performance. Show all posts
Showing posts with label performance. Show all posts

Thursday, July 23, 2009

Homemade recipe

This is another example of how simple "homemade" approach significantly outperforms patented generic methods. How often you needed to convert byte array into String object and vice versa? The recommended methods always require the name of Charset. Since in my case the charset is always UTF-8, I hardcoded it.
When converting from byte array to String, something like following can be used:
final static String b2s_recommended(byte[] bb) {
    try {
        return new String(bb, 0, bb.length, "UTF-8");
    } catch(Exception ex) {
        throw new RuntimeException(ex.getMessage());
    }
}
   
   

When converting from String to byte array something like following can be used:
final static byte[] s2b_recommended(String s) {
    try {
        return s.getBytes("UTF-8");
    } catch(Exception ex) {
        throw new RuntimeException(ex.getMessage());
    }
}
   
   

Corresponding "homemade" methods that don't pretend to be generic, can look like following:
final static String b2s_homemade(byte[] bb) {
    char[] cc = new char[bb.length];
    for (int i = 0; i < bb.length; ++i) {
        cc[i] = (char) bb[i];
    }
    return new String(cc);
}
   
final static byte[] s2b_homemade(String s) {
    byte[] bb = new byte[s.length()];
    for (int i = 0; i < bb.length; ++i) {
        bb[i] = (byte) s.charAt(i);
    }
    return bb;
}
   

On my computer homemade b2s outperformed recommended one with factor of 4.2 . For the s2b the performance bust was 6.0 !

Sunday, April 26, 2009

Legend Confirmed

There is number of facts circulating in the form of urban legends. And there are sites devoted to these facts. The sites discuss the matters and most of the time disprove the statement made by the legend. I think many statements in programming can be classified as legends of the kind. That's why before selecting a solution to some problem it makes sense to double check facts that can affect your decision.

One of the commonly admitted facts I knew for a long time was that reflection in Java is slow. I believed the fact in general, but when writing my own class that needed generic construction of an object I decided to test the legend. My hope was that for a task as simple as using of default constructor call to new cannot be much better than call to class.newInstance(). Here is my test program (I took some precautions to avoid optimizing out creation of the objects from the loop):
import java.util.GregorianCalendar;
public class Console {
    static class Foo {
        long l;
        double d;
        String s = "foo";
        Foo() {
            l = new GregorianCalendar().getTimeInMillis();
            d = (double)(l * l);
        }
    }
    public static void main(String[] args) {
        try {
            long l1 = new GregorianCalendar().getTimeInMillis();
            double sum = 0;
            Class<Foo> clazz = Foo.class;
            for(int i = 0; i < 1000000; ++i) {
                Foo foo = (Foo) clazz.newInstance();
                sum += foo.d;
                foo = null;
            }
            long l2 = new GregorianCalendar().getTimeInMillis();
            System.out.println("" + sum + ": " + (l2-l1));
            sum = 0;
            for(int i = 0; i < 1000000; ++i) {
                Foo foo = new Foo();
                sum += foo.d;
                foo = null;
            }
            l1 = new GregorianCalendar().getTimeInMillis();
            System.out.println("" + sum + ": " + (l1-l2));
        } catch (Throwable e) {}
    }
}
   


Here is the result: I was wrong. Creation of 1,000,000 objects on my computer took ~1,700 millis with the call to class.newInstance() and ~1,050 millis with the call to new. Conclusion: some legends can be trusted. But you never know which.