0

I am using google caliper to run a very simple benchmark on a method. I am getting the following exception.

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.code4refernce.caliper.SimpleCaliperTest.timeStringLen(SimpleCaliperTest.java:24)
    at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.google.caliper.SimpleBenchmark$1.run(SimpleBenchmark.java:125)
    at com.google.caliper.TimeMeasurer.measureReps(TimeMeasurer.java:174)
    at com.google.caliper.TimeMeasurer.warmUp(TimeMeasurer.java:62)
    at com.google.caliper.TimeMeasurer.run(TimeMeasurer.java:122)
    at com.google.caliper.InProcessRunner.run(InProcessRunner.java:74)
    at com.google.caliper.InProcessRunner.run(InProcessRunner.java:49)
    at com.google.caliper.InProcessRunner.main(InProcessRunner.java:103)

I don't understand why I am getting this exception. I tried to increase the JVM memory then also I get this exception.

The benchmark code is as following.

package com.code4refernce.caliper;
import java.util.Random;
import java.util.regex.Pattern;

import com.google.caliper.Param;
import com.google.caliper.SimpleBenchmark;

public class SimpleCaliperTest extends SimpleBenchmark {
    String regex = "(\\d{3}-\\d{3}-\\d{4})|(\\d{10})";
    Pattern REGEX_PATTERN = Pattern.compile(regex);

    String mdn[];
    Random random;
    @Param
    int index;

    @Override 
    protected void setUp() {
         random = new Random(0);
        mdn = new String[4];
            mdn[0] = "098412sdfasdf8000";
            mdn[1] = "11345";
            mdn[2] = "1423567890";
            mdn[3] = "123-456-7890";
    }


    public Boolean[] timeStringLen(int reps){
        Boolean results[] = new Boolean[reps];

        for(int i = 0; i<reps; i ++){

            results [i]= mdnCheckRegularMethod(mdn[index]);
        }
        return results;
    }
    public Boolean[] timeRegex(int reps){
        Boolean results[] = new Boolean[reps];
        for(int i = 0; i<reps; i ++){

            results[i]=mdnCheckRegEx(mdn[index]);
        }
        return results;
    }
    private boolean mdnCheckRegularMethod(String mdn){
        boolean result = false;

        if(mdn.length()==10){
            try{
                Integer.parseInt(mdn);
                result = true;
            }catch(Exception e){
                result = false;
            }
        }
        else if(mdn.length() == 13){
            byte[] bmdn = mdn.getBytes();
            for(int i = 0; i<bmdn.length; i++){
                if((i == 3 || i == 6) && bmdn[i] == '-'){}
                else if(bmdn[i] >= '0' && bmdn[i]<='9'){}
                else{
                    result = false;
                    break;
                }
            }
        }
        else{
            result = false;
        }
        return result;
    }

    private boolean mdnCheckRegEx(String mdn){
        return REGEX_PATTERN.matcher(mdn).matches();
    }
}

and the main class which runs the caliper benchmark.

package com.code4refernce.caliper;
import com.google.caliper.Runner;

    public class CaliperRunner {
        public static void main(String[] args) {
            String myargs[] = new String[2];
            myargs[0] = new String("-Dindex=0,1,2,3");
            myargs[1] = new String("-Jmemory=-Xms1024m ");
            Runner.main(SimpleCaliperTest.class, myargs);
        }
    }

I don't understand whats going wrong here. Can someone point out?

Rakesh
  • 3,987
  • 10
  • 43
  • 68
  • Which one is line 24? The Boolean array or the call to mdnCheckRegularMethod? – home Aug 29 '12 at 05:40
  • Boolean[] results = new Boolean[reps]; \\line24 – Rakesh Aug 29 '12 at 05:43
  • 1
    What if you use the native `boolean` type for array initialization? – home Aug 29 '12 at 05:44
  • I tried it and worked. thanks. But couldn't get the reason behind this behavior. – Rakesh Aug 29 '12 at 05:56
  • The `Boolean` array creates the number of `reps` null references to the Boolean type (approx 8 byte per reference). Whereas as the primitive alternative just allocates space required for the primitive type, see e.g. http://stackoverflow.com/questions/3733215/memory-requirements-of-an-object-reference-on-a-64-bit-jvm. In other words, it might fail again in the future as it depends on the size of `reps`. (I'm not familar with caliper). – home Aug 29 '12 at 06:24
  • Does your benchmark write to System.out ? – Jesse Wilson Aug 29 '12 at 12:54

1 Answers1

1

Your method timeStringLen(int reps) may be called with reps up to Integer.MAX_VALUE. You could give your VM more memory via the -Xmx switch, but you'd better not allocate needlessly big arrays, as it's not needed at all:

public boolean timeStringLen(int reps){
    boolean result = false;

    for(int i = 0; i<reps; i ++){
        result ^= mdnCheckRegularMethod(mdn[index]);
    }
    return result;
}

This does the same job, the only reason for returning a value is to prevent the JIT from optimizing it all away. Xoring is enough here, counting the cases when the method returned true is another possibility.


But there's most probably another problem with your benchmark: The high values of reps used show that it's running faster then I'd expect. The result of each iteration seems to be the same and I'd guess that you loops gets optimized to something like

result[i] = Boolean.TRUE

which I don't think you want to measure. Using something like

Random random = new Random(0);
mdn = new String[4][1<<16];
for (int i=0; i<mdn.length; ++i) {
    mdn[0][i] = String.format("%03ddsfasdf00000", random.nextInt(1000));
    mdn[1][i] = String.format("%04d", random.nextInt(10000));
    mdn[2][i] = String.format("%10d", random.nextInt((int) 1e10));
    mdn[3][i] = String.format("%03d-%03d-%03d", random.nextInt(1000), random.nextInt(1000), random.nextInt(1000));
}

would help.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • Thanks for the answer. I edited the code(check out the first post in this thread). I don't know why regular expression is not performing that well. Is something wrong here? – Rakesh Aug 29 '12 at 15:33
  • @Rakesh You'd better have created a new question, as the original one has been answered. The title doesn't match anymore. I'd copy the text into a new question and rollback the changes here. – maaartinus Aug 29 '12 at 16:20