java 基准测试 格式_不要猜,要测试!—Java 微基准测试框架 JMH

在以前,想要知道自己写的程序性能和程序运行时间,一般都是定义一个startTime=System.nanoTime,再定义一个endTime=System.nanoTime,最后他们之间的差便是程序的运行时间。

但是,这样的测试仅仅是粗略的测试此段代码在此时的运行时间,结果并不一定可靠。这里建议使用一个更加官方的测试工具:JMH–Java微基准测试框架

Code Tools: jmh

JMH是由OpenJDK官方发布的一种Java工具,用于构建,运行和分析用Java和其他语言编写的针对JVM的nano / micro / milli / macro基准测试。

官方地址:https://openjdk.java.net/projects/code-tools/jmh/

使用JMH,你可以:

当需要优化一个方法的时候,可以使用JMH测试方法运行时间,测试是否达到优化效果

当需要知道一个方法大概的执行时间的时候

当需要知道不同的参数对同一个方法的运行效率的影响的时候

总之,JMH在方法级别的运行时间测试上得到的结果是比较权威的。

Go Start

官方推荐JMH应该使用Maven构建。

当我们仅仅需要测试一个独立的方法的时候,我们可以直接构建一个JMH Maven骨架(archetype)

mvn archetype:generate \

-DinteractiveMode = false \

-DarchetypeGroupId = org.openjdk.jmh \

-DarchetypeArtifactId = jmh- java -benchmark-archetype \

-DgroupId = org.sample \

-DartifactId = test \

-Dversion = 1.0

当我们想在已有到的项目的基础上进行JMH测试的时候,我们可以直接添加Maven依赖:

org.openjdk.jmh

jmh-core

${jmh.version}

org.openjdk.jmh

jmh-generator-annprocess

1.21

${jmh.version}

添加完依赖后,我们就可以编写性能测试方法,这里和我们经常使用的单元测试方法差不多:

这里我们测试下HashMap中,使用位运算代替取模运行的效率到底有没有提升

@BenchmarkMode(Mode.Throughput)

@Warmup(iterations = 3)

@Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS)

@Threads(8)

@Fork(2)

@OutputTimeUnit(TimeUnit.MILLISECONDS)

@State(Scope.Benchmark)

public class Test {

@Param({"18","2035","12345"})

private int param;

@Benchmark

public void test(){

int c=(16-1)¶m;

}

@Benchmark

public void test2(){

int c=param%16;

}

@Setup

public void prepare() {

}

}

执行:

执行方式分两种

由于JMH测试一般测试好几轮取平均值,因此有时候测试时间比较长,这个时候我们可以使用Maven将测试打包,然后放在服务器上测试:

mvn clean package

然后会在对应的目录/target下生成jar包,直接

java -jar xxx.jar

运行即可。

对于比较小的项目,我们可以直接编写Main方法,在编译器上运行即可:

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

Options options = new OptionsBuilder()

.include(Test.class.getSimpleName())

.output("G:/Benchmark.log")

.build();

new Runner(options).run();

}

这里我们指定了测试类和日志输出路径。

执行完成后可以获取测试结果:

# JMH version: 1.21

# VM version: JDK 1.8.0_181, Java HotSpot(TM) 64-Bit Server VM, 25.181-b13

# VM invoker: H:\java\jdk1.8\jre\bin\java.exe

# VM options: -Dvisualvm.id=789216946682180 -javaagent:H:\idea\IntelliJ IDEA 2018.2.2_2\lib\idea_rt.jar=64857:H:\idea\IntelliJ IDEA 2018.2.2_2\bin -Dfile.encoding=UTF-8

# Warmup: 3 iterations, 10 s each

# Measurement: 10 iterations, 5 s each

# Timeout: 10 min per iteration

# Threads: 8 threads, will synchronize iterations

# Benchmark mode: Throughput, ops/time

# Benchmark: com.dengchengchao.Test.test

# Parameters: (param = 18)

...

...

...

Benchmark (param) Mode Cnt Score Error Units

Test.test 18 thrpt 20 11201407.357 ± 288038.173 ops/ms

Test.test 2035 thrpt 20 11155849.134 ± 411417.605 ops/ms

Test.test 12345 thrpt 20 11242387.836 ± 124937.944 ops/ms

Test.test2 18 thrpt 20 10618259.409 ± 166619.563 ops/ms

Test.test2 2035 thrpt 20 10566613.381 ± 185395.887 ops/ms

Test.test2 12345 thrpt 20 10497633.170 ± 226031.760 ops/ms

可以发现,结果中说明了每个方法的平均吞吐量以及误差范围等,我们可以得到结果:在我的电脑中,JDK 1.8环境下,使用Java 的位运算和取模运行时间相差不大,

在这里,使用JMH测试方法运行就算完成了,其实也比较简单,并且比自己写System.nanoTime更加准确。

注解介绍

在上面的方法测试中,我们发现了很多新的注解。下面对上这些注解进行简单介绍:

@Benchmark(测试方法标记注解)

标记测试方法,和@Test注解差不多,标注后在运行的时候JMH将会对此 方法进行测试。

在官方的HelloWorld例子仅仅使用了这一个注解,因为这里的注解其实也是一种启动参数,不仅仅可以通过注解表示,还可以使用类似java -jar xxx.jar -f 1 -t 2方式指定,也可以在编写Main方法的时候,使在构建方法Builder的时候指定。这种灵活的参数指定方式,可以在不同的场景的灵活应用。

@BenchmarkMode(基准测试类型)

Throughput : 吞吐量,比如:1s内可以执行多少次调用

AverageTime: 调用的平均时间

SampleTIme: 随机取样,最后输出取样结果分布,例如“99%的调用在xxx毫秒以内,99.99%的调用在xxx毫秒以内”

SingleShotTime:以上模式都是默认一次 iteration 是 1s,唯有 SingleShotTime 是只运行一次。往往同时把 warmup 次数设为0,用于测试冷启动时的性能。

All:执行所有的类型测试

@Measurement(基本测试参数)

iterations 进行测试的轮次

time 每轮进行的时长

timeUnit 时长单位

@Warmup

基准测试预热选项,有时候在JVM的优化下(比如JIT),前几次测试的结果一般不准确,因此我们可以指定预热时间,将前几次的测试结果丢弃。@Warmup的选项和@Measurement是相同的

@Threads

每个进程中的测试线程,根据具体情况选择,一般为cpu乘以2。

@Fork

启动测试进程数,比如@Fork(2),那么JMH会启动两个进程进行测试

@OutputTimeUnit

基准测试时间单位,比如秒,毫秒,微秒等

@Param

指定参数,可以用来测试在不同参数的情况下方法的运行效率

@Setup

方法级注解,被标记的方法会在启动前运行,一般用来在测试之前进行一些准备工作,比如数据初始化等

@TearDown

方法级注解,被标记的方法会在测试完成后运行,一般用来在测试之后的一些清理工作,比如关闭连接等

@State

当使用@Setup参数的时候,必须在类上加这个参数,不然会提示无法运行。

State 用于声明某个类是一个“状态”,然后接受一个 Scope 参数用来表示该状态的共享范围。 因为很多 benchmark 会需要一些表示状态的类,JMH 允许你把这些类以依赖注入的方式注入到 benchmark 函数里。Scope 主要分为三种。

Thread: 该状态为每个线程独享。

Group: 该状态为同一个组里面所有线程共享。

Benchmark: 该状态在所有线程间共享。

官方文档中,有个比较好的例子来展示@state的使用:JMHSample_03_States

在JMH能做的,远不止这些,想要了解更多,可以阅读官方文档

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值