Калипер: JVM выдает исключение OutOfMemoryError

Я использую штангенциркуль Google для запуска очень простого теста метода. Я получаю следующее исключение.

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)

Я не понимаю, почему я получаю это исключение. Я попытался увеличить память JVM, а затем получил это исключение.

Код теста выглядит следующим образом.

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();
    }
}

и основной класс, который запускает тест суппорта.

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);
        }
    }

Я не понимаю, что здесь происходит не так. Может кто-нибудь указать?


person Rakesh    schedule 29.08.2012    source источник
comment
Какая из строк 24? Логический массив или вызов mdnCheckRegularMethod?   -  person home    schedule 29.08.2012
comment
Boolean[] results = new Boolean[reps]; \\строка24   -  person Rakesh    schedule 29.08.2012
comment
Что, если вы используете собственный тип boolean для инициализации массива?   -  person home    schedule 29.08.2012
comment
Я пробовал и работал. благодаря. Но не мог понять причину такого поведения.   -  person Rakesh    schedule 29.08.2012
comment
Массив Boolean создает количество reps нулевых ссылок на тип Boolean (примерно 8 байт на ссылку). В то время как примитивная альтернатива просто выделяет пространство, необходимое для примитивного типа, см., например. stackoverflow.com/questions/3733215/. Другими словами, в будущем он может снова выйти из строя, так как это зависит от размера reps. (я не знаком с суппортом).   -  person home    schedule 29.08.2012
comment
Ваш тест записывает в System.out ?   -  person Jesse Wilson    schedule 29.08.2012


Ответы (1)


Ваш метод timeStringLen(int reps) может вызываться с reps до Integer.MAX_VALUE. Вы можете дать своей ВМ больше памяти с помощью переключателя -Xmx, но лучше не выделять излишне большие массивы, так как это вообще не нужно:

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

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

Это делает ту же работу, единственная причина для возврата значения - не дать JIT оптимизировать все это. Xoring здесь достаточно, считая случаи, когда метод возвращал true, это еще одна возможность.


Но, скорее всего, есть еще одна проблема с вашим тестом: высокие значения reps показывают, что он работает быстрее, чем я ожидал. Результат каждой итерации кажется одинаковым, и я предполагаю, что ваши циклы оптимизируются до чего-то вроде

result[i] = Boolean.TRUE

который я не думаю, что вы хотите измерить. Используя что-то вроде

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));
}

помог бы.

person maaartinus    schedule 29.08.2012
comment
Спасибо за ответ. Я отредактировал код (посмотрите первый пост в этой теме). Я не знаю, почему регулярное выражение не работает так хорошо. Что-то здесь не так? - person Rakesh; 29.08.2012
comment
@Rakesh Вам лучше создать новый вопрос, так как на исходный был дан ответ. Название уже не соответствует. Я бы скопировал текст в новый вопрос и отменил изменения здесь. - person maaartinus; 29.08.2012