我们有一个应用程序,其中我们需要过滤某些类型的文件。我们认为正则表达式的方法比简单的Strings.endsWith()方法要快。但是为了验证该假设,我们做了一个小型基准测试。以下是我们使用的工作代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test{

       private static Pattern pattern;
       private static Matcher matcher;
       private static final String IMAGE_PATTERN = "([^\\s]+(\\.(?i)(jpeg|jpg|png|gif|bmp|css|js))$)";

       private static String[] files = {"jpeg","jpg","png","gif","bmp","css","js"};

    public static void main(String args[]) throws Exception {

        pattern = Pattern.compile(IMAGE_PATTERN);

        //Input Strings
        String input = args[0];
        String[] inputArr = input.split(",");

        Integer iterations = 10000;
        Integer i = 0;

        Long t1 = System.currentTimeMillis();

        while(i < iterations){

            for (int j = 0; j < inputArr.length; j++) {
                validateReg(inputArr[j]);
            }
            i++;
        }
        System.out.println("Time taken using regex:"+(System.currentTimeMillis() - t1));

        t1 = System.currentTimeMillis();
        i=0;
        while(i < iterations){

            for (int j = 0; j < inputArr.length; j++) {
                validateStr(inputArr[j]);
            }
            i++;
        }
        System.out.println("Time taken using .endsWith :"+(System.currentTimeMillis() - t1));

    }

      public static boolean validateReg(final String file){

          matcher = pattern.matcher(file);
          return matcher.matches();

       }

      public static boolean validateStr(final String file){

          for (int i = 0; i < files.length; i++) {

              if(file.endsWith(files[i])){
                  return true;
              }
        }
            return false;
       }
 }


对于输入abc.jpg,efg.css,jij.jpeg,test.java,best.css,not.gif,f.exe,test.js,su.css,not.js,yes,png

它打印:

Time taken using regex:89
Time taken using .endsWith :6


并且多次运行的数字是相同的。即使更改while循环的执行顺序,结果也相同。看起来String.endsWith()比其regex等效要快得多。

现在我的问题是:这种基准测试方法是否可以正确地得出结论?还是有更好,更可靠的方法来测试这种情况?

最佳答案

String.endsWith通过简单比较比较字符串末尾的字节(字符)来工作。另一方面,正则表达式需要更多的时间来解析正则表达式,对其进行编译,构建匹配器并执行它。但是关于您的问题:此测试至少可以证明regexp与endsWith之间存在差异。为了进行更精确的测量,您应该尽可能早地选择开始时间戳,可能要尽快排除循环开销和结束时间戳,然后执行一些计算(求和周期)。例如:

long t0, t1, tt = 0L;
for (int i = 0; i < ITERATIONS; i++) {
    t0 = System.currentTimeMillis();
    //- Execute the code its execution time you want to measure here.
    t1 = System.currentTimeMillis();
    tt += (t1 - t0);
}
System.out.println("Total time: " + tt + "ms");


要进行更精确的测量,可以使用System.nanoTime()

10-08 12:59