为什么 Java 编译的正则表达式比 String::split 中解释的运行速度慢?

Jeg*_*ovs 2 java regex benchmarking split jmh

我正在尝试改进以下代码:

\n
    public int applyAsInt(String ipAddress) {\n        var ipAddressInArray = ipAddress.split("\\\\.");\n        ...\n
Run Code Online (Sandbox Code Playgroud)\n

所以我将正则表达式编译成静态常量:

\n
    private static final Pattern PATTERN_DOT = Pattern.compile(".", Pattern.LITERAL);\n\n    public int applyAsInt(String ipAddress) {\n        var ipAddressInArray = PATTERN_DOT.split(ipAddress);\n        ...\n
Run Code Online (Sandbox Code Playgroud)\n

其余代码保持不变。

\n

令我惊讶的是,新代码比以前的代码慢。\n以下是测试结果:

\n
Benchmark                                (ipAddress)  Mode  Cnt    Score    Error  Units\nConverterBenchmark.mkyongConverter           1.2.3.4  avgt   10  166.456 \xc2\xb1  9.087  ns/op\nConverterBenchmark.mkyongConverter       120.1.34.78  avgt   10  168.548 \xc2\xb1  2.996  ns/op\nConverterBenchmark.mkyongConverter   129.205.201.114  avgt   10  180.754 \xc2\xb1  6.891  ns/op\nConverterBenchmark.mkyong2Converter          1.2.3.4  avgt   10  253.318 \xc2\xb1  4.977  ns/op\nConverterBenchmark.mkyong2Converter      120.1.34.78  avgt   10  263.045 \xc2\xb1  8.373  ns/op\nConverterBenchmark.mkyong2Converter  129.205.201.114  avgt   10  331.376 \xc2\xb1 53.092  ns/op\n
Run Code Online (Sandbox Code Playgroud)\n

请帮助我理解为什么会发生这种情况。

\n

Tho*_*ger 12

String.split有专门针对此用例的代码:

https://github.com/openjdk/jdk17u/blob/master/src/java.base/share/classes/java/lang/String.java#L3102

        /* fastpath if the regex is a
         * (1) one-char String and this character is not one of the
         *     RegEx's meta characters ".$|()[{^?*+\\", or
         * (2) two-char String and the first char is the backslash and
         *     the second is not the ascii digit or ascii letter.
         */
Run Code Online (Sandbox Code Playgroud)

这意味着当使用split("\\.")字符串时,实际上不会使用正则表达式来分割 - 该方法直接在'.'字符处分割字符串。

当您编写时,这种优化是不可能的PATTERN_DOT.split(ipAddress)