java - 卡尺 : JVM throws OutOfMemoryError Exception

标签 java jvm caliper

我正在使用 google caliper 对方法运行一个非常简单的基准测试。我收到以下异常。

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

我不明白这里出了什么问题。有人能指点一下吗?

最佳答案

您的方法 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 完全优化它。异或在这里就足够了,计算方法返回 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));
}

会有帮助。

关于java - 卡尺 : JVM throws OutOfMemoryError Exception,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12171246/

相关文章:

java - spring-integration DSL - 这种行为似乎不对?

java - 由 Bitnami 提供支持的 Android 版 Parse(好友列表)

java - jdbc 无法与 java 连接

java - 根据位置格式化java中的字符串

java - 为什么 JVM 不从数据库加载类?

java - 获取应用程序正常运行时间

java - 甲骨文 JVM : invokespecial instruction

java - 运行 caliper 命令行

java - Python 或 Java 中强大的 json 解析器