这是一个简单的用来对Java代码做性能评估的工具库。
特性
- 轻量级(jar包仅
26kb) - API简单易用
- 易于集成或扩展
Maven集成
<dependency>
<groupId>com.zxd</groupId>
<artifactId>stalker</artifactId>
<version>1.0.0</version>
</dependency>
API 介绍和使用
预先准备
在对Java方法做性能测试之前,先准备好待测试的类和方法:
/** * 用于测量(仅测试使用)该类中的方法的执行耗时的类. * * @author zhangxianda on 2019-02-03. */ public class MyTestService {<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">Logger</span> log <span class="token operator">=</span> <span class="token class-name">LoggerFactory</span><span class="token punctuation">.</span><span class="token function">getLogger</span><span class="token punctuation">(</span><span class="token class-name">MyTestService</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/** * 测试方法1,模拟业务代码耗时 2~5 ms,且会有约 1% 的几率执行异常. */</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 模拟运行时抛出异常.</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">nextInt</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">MyServiceException</span><span class="token punctuation">(</span><span class="token string">"My Service Exception."</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// 模拟运行占用约 2~5 ms 的时间.</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2L</span> <span class="token operator">+</span> <span class="token keyword">new</span> <span class="token class-name">Random</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">nextInt</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/** * 测试方法2,模拟业务代码运行占用约 2 ms 的时间. */</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">fastHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2L</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/** * 本线程调用该方法时,睡眠指定时间,用来模拟业务耗时. * * @param time 时间 */</span> <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token keyword">long</span> time<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span> log<span class="token punctuation">.</span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string">"InterruptedException"</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">interrupt</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
}
Stalker类
1. 最简示例
以下代码将会预热5次,然后在单线程下正式执行10次,从而将运行结果计算统计并输出出来:
public static void main(String[] args) {
Stalker.run(() -> new MyTestService().hello());
}
以上结果将默认在控制台输出:
+-----------------------------------------------------------------------------------------------------------------------------------------+
| threads: 1, concurrens: 1, warmups:5, runs: 10, printErrorLog: false |
+---+----------+-------+---------+---------+----------+---------+---------+---------+---------+---------------------+---------------------+
| | Costs | Total | Success | Failure | Sum | Avg | Min | Max | StdDev | 95% LowerConfidence | 95% UpperConfidence |
+---+----------+-------+---------+---------+----------+---------+---------+---------+---------+---------------------+---------------------+
| 1 | 35.33 ms | 10 | 10 | 0 | 35.29 ms | 3.53 ms | 2.56 ms | 4.81 ms | 0.85 ms | 3.0 ms | 4.06 ms |
+---+----------+-------+---------+---------+----------+---------+---------+---------+---------+---------------------+---------------------+
2. 更全示例
以下代码表示,两个方法hello()和fastHello()将会预热1000次,在1000个线程200个并发下,每次执行10次:
Stalker.run(Options.of(1000, 200).warmups(1000).runs(10),
() -> new MyTestService().hello(),
() -> new MyTestService().fastHello());
以上结果将默认在控制台输出:
+------------------------------------------------------------------------------------------------------------------------------------------+
| threads: 1000, concurrens: 200, warmups:1000, runs: 10, printErrorLog: false |
+---+-----------+-------+---------+---------+---------+---------+---------+----------+---------+---------------------+---------------------+
| | Costs | Total | Success | Failure | Sum | Avg | Min | Max | StdDev | 95% LowerConfidence | 95% UpperConfidence |
+---+-----------+-------+---------+---------+---------+---------+---------+----------+---------+---------------------+---------------------+
| 1 | 454.33 ms | 10000 | 9900 | 100 | 36.79 s | 3.72 ms | 2.01 ms | 11.89 ms | 1.31 ms | 3.69 ms | 3.74 ms |
| 2 | 159.94 ms | 10000 | 10000 | 0 | 21.72 s | 2.17 ms | 2.01 ms | 3.24 ms | 0.15 ms | 2.17 ms | 2.18 ms |
+---+-----------+-------+---------+---------+---------+---------+---------+----------+---------+---------------------+---------------------+
结果说明:
Costs: 实际正式运行所消耗的总时间Total: 正式运行的总次数Success: 正式运行的成功次数Failure: 正式运行的失败次数Sum: 每次运行的耗时结果求和之后的值Avg: 所有运行耗时结果的算术平均数Min: 所有运行耗时结果中最小值Max: 所有运行耗时结果中最大值StdDev: 所有运行耗时结果的标准方差95% LowerConfidence: 95%置信区间的最小边界值95% LowerConfidence: 95%置信区间的最大边界值
3. 主要方法
void run(Runnable... runnables): 对若干个要执行的代码做性能测量评估.void run(Options options, Runnable... runnables): 通过自定义的Options对若干个要执行的代码做性能测量评估.
Options类
Options表示做性能测量时的选项参数
主要属性如下
name: 选项参数的名称threads: 正式执行的线程数,默认为1。concurrens: 正式多线程下执行的并发数,默认为1。warmups: 单线程下的预热次数,默认5。runs: 每个线程正式执行的次数,默认10。printErrorLog: 是否打印错误日志,默认false。outputs: 将测量结果通过多种方式(集合)输出出来,默认为输出到控制台,可自定义实现MeasureOutput接口。
主要方法
以下是构造Options实例的若干重载方法:
Options of(String name)Options of(int runs)Options of(String name, int runs)Options of(int threads, int concurrens)Options of(String name, int threads, int concurrens)Options of(String name, int threads, int concurrens, int runs)
其他方法:
boolean valid(): 校验Options相关参数是否合法Options named(String name): 设置 Options 实例的 name 属性Options threads(int threads): 设置 Options 实例的 threads 属性Options concurrens(int concurrens): 设置 Options 实例的 concurrens 属性Options warmups(int warmups): 设置 Options 实例的 warmups 属性Options runs(int runs): 设置 Options 实例的 runs 属性Options printErrorLog(boolean printErrorLog): 设置 Options 实例的 printErrorLog 属性Options outputs(MeasureOutput... measureOutputs): 自定义设置 Options 实例的 MeasureOutput 输出通道
Assert类
Assert类主要用来做断言使用。
示例
Assert.assertFaster(Options.of(),
() -> new MyTestService().fastHello(),
() -> new MyTestService().hello());
许可证
本 stalker 类库遵守 Apache License 2.0 许可证。