我正在使用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
开关为VM提供更多的内存,但是最好不要分配不必要的大数组,因为根本不需要它:
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));
}
有助于。