之前写了文章介绍 Groovy 关键字as
,我个人是十分推荐使用,特别在基础类型数据转换场景下,as
关键字能够随心所欲将数据转换成我们需要的类型。但在实际使用过程中,由于没看到具体实现,也难以对as
关键字的性能有个了解。所以今天准备测试几种我经常使用的场景进行as
关键字的性能测试。
这次我准备使用Java微基准测试神器JMH初探来进行基准测试,自从用上了JMH
,就再也没有自己写过基准测试用例了。十分推荐。
String 转 double
这个是非常常用的,还有一个类似的 String 转 int,由于极其相似就不再测试了。其实结论大差不差。
下面是我的测试用例,分成了两部分,一部分 Groovy 类,用于实现各种不同方法,一部分是 JMH 的内容。原因是我还没有找到 JMH 完美兼容 Groovy 的方法。
Groovy 类:
class JmhG {
static double groovy(String str) {
str as double
}
static double java(String str) {
Double.valueOf(str);
}
static double java2(String str) {
str.toBigDecimal()
}
}
复制代码
JMH 测试 Case:
import com.funtester.frame.SourceCode;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS)
@Threads(2)
@Fork(1)
@State(value = Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class JmhT extends SourceCode {
@Param(value = {"13323222320", "2323230.2323233232", "532873873828382738201"})
private String str;
@Benchmark
public void groovy() {
JmhG.groovy(str);
}
@Benchmark
public void java() {
JmhG.java(str);
}
@Benchmark
public void javaForce() {
JmhG.java2(str);
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.include(JmhT.class.getSimpleName())
.result("result.json")
.resultFormat(ResultFormatType.JSON)
.forks(1)
.threads(2)
.warmupIterations(1)
.warmupBatchSize(1)
.measurementIterations(2)
.measurementBatchSize(2)
.build();
new Runner(options).run();
}
}
复制代码
测试结果:
Benchmark (str) Mode Cnt Score Error Units
JmhT.groovy 13323222320 thrpt 2 9314.268 ops/ms
JmhT.groovy 2323230.2323233232 thrpt 2 4219.366 ops/ms
JmhT.groovy 532873873828382738201 thrpt 2 4442.363 ops/ms
JmhT.java 13323222320 thrpt 2 19418.404 ops/ms
JmhT.java 2323230.2323233232 thrpt 2 5679.708 ops/ms
JmhT.java 532873873828382738201 thrpt 2 6331.530 ops/ms
JmhT.javaForce 13323222320 thrpt 2 27996.119 ops/ms
JmhT.javaForce 2323230.2323233232 thrpt 2 3400.895 ops/ms
JmhT.javaForce 532873873828382738201 thrpt 2 1614.033 ops/ms
复制代码
从结果看出来,Java 自带的方法Double.valueOf(str)
性能最好,Groovy 关键字as
次之,而org.codehaus.groovy.runtime.StringGroovyMethods#toBigDecimal
这个方法的性能有点飘忽不定,在 int 类型字符串情况下,它性能最高。在较长小数点情况下,又稍逊一筹,到了 long 类型数据直接崩了。各位可以根据使用场景自行选择。
数字转 String
这个用得少,通常直接使用 Java 自带的加一个空字符串实现。不过趁着这次测试看一下各方面不同的性能表现。
Groovy 方法类:
class Jmh {
static String groovy(double number) {
number as String
}
static String java(double number) {
number + ""
}
static String java2(double number) {
number.toString()
}
}
复制代码
JMH 的测试 Case 就不发了,复用上面的,下面是测试结果:
Benchmark (num) Mode Cnt Score Error Units
JmhT.groovy 13323222320 thrpt 2 5533.081 ops/ms
JmhT.groovy 2323230.2323233232 thrpt 2 2713.348 ops/ms
JmhT.groovy 532873873828382738201 thrpt 2 2845.852 ops/ms
JmhT.java 13323222320 thrpt 2 7226.492 ops/ms
JmhT.java 2323230.2323233232 thrpt 2 2572.057 ops/ms
JmhT.java 532873873828382738201 thrpt 2 2652.787 ops/ms
JmhT.javaForce 13323222320 thrpt 2 19337.224 ops/ms
JmhT.javaForce 2323230.2323233232 thrpt 2 3979.556 ops/ms
JmhT.javaForce 532873873828382738201 thrpt 2 3940.559 ops/ms
复制代码
可以看出 Groovy 方法性能明显弱于 Java 的视线,而两种 Java 实现性能相差无几。这里建议追求极限性能的使用 Java 的java.lang.Double#toString()
或者java.lang.Double#toString(double)
这俩其实是一个方法。
double 转 int
下面分享一下数字类型之间相互转换,以 double 转 int 为例。
Groovy 方法类:
class JmhG {
static int groovy(double d) {
d as int
}
static int java(double d) {
(int) d
}
}
复制代码
JMH 测试方法部分内容:
参数化做了点修改,其他内容不变。
@Param(value = {"13.20", "2323230.2323233232"})
private double num;
复制代码
下面是测试结果:
Benchmark (num) Mode Cnt Score Error Units
JmhT.groovy 13.20 thrpt 2 16441.947 ops/ms
JmhT.groovy 2323230.2323233232 thrpt 2 13305.805 ops/ms
JmhT.java 13.20 thrpt 2 846022.670 ops/ms
JmhT.java 2323230.2323233232 thrpt 2 861913.384 ops/ms
复制代码
结论差不多,Groovy 关键字as
的性能更差了。几十倍的差距已经无法直视,后面处理脚本层面会用到 groovy 关键字as
,框架部分和业务部分都会避免使用as
关键字了。
结论
结尾放一下 Groovy 关键字as
的总结陈词。
Groovy 是一种基于 JVM 的动态语言,它可以与 Java 平滑地集成,支持 Java 的语法和库,并且具有更高的灵活性和易用性。在 Groovy 中,as 是一个关键字,它用于类型转换和类型推断。
在 Groovy 中,as 关键字用于将一个对象转换为指定类型的对象。例如,可以使用 as 关键字将一个字符串转换为整数,或将一个 Map 转换为 JSON 字符串。as 关键字还可以用于类型推断,即根据上下文推断出对象的类型。例如,在 Groovy 中,可以使用 def 关键字定义一个变量,然后根据赋值语句自动推断出变量的类型。
as 关键字的用途有以下几点:
类型转换:as 关键字可以将一个对象转换为指定类型的对象,方便程序员进行类型转换操作。
类型推断:as 关键字可以根据上下文推断出对象的类型,简化了变量定义和类型转换的代码。
继承和多态:as 关键字可以用于继承和多态的场景,比如将一个子类对象转换为父类对象或将一个接口对象转换为实现类对象。
总之,as 关键字是 Groovy 语言的一个重要特性,它可以帮助程序员更方便地进行类型转换和类型推断操作,提高代码的可读性和可维护性,同时也支持继承和多态的特性,方便程序员进行面向对象编程。
FunTester 原创专题推荐~~
-- By FunTester
评论