mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-10-21 09:23:44 +08:00
u
This commit is contained in:
@@ -25,13 +25,7 @@
|
||||
<meta name="generator" content="Hexo 4.2.0">
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div class="book-container">
|
||||
|
||||
<div class="book-sidebar">
|
||||
@@ -55,289 +49,148 @@
|
||||
<li><a href="/" class="current-tab">首页</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li><a href="../">上一级</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul class="uncollapsible">
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/01 开篇词:一次服务雪崩问题排查经历.md.html">01 开篇词:一次服务雪崩问题排查经历.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/02 为什么需要服务降级以及常见的几种降级方式.md.html">02 为什么需要服务降级以及常见的几种降级方式.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/03 为什么选择 Sentinel,Sentinel 与 Hystrix 的对比.md.html">03 为什么选择 Sentinel,Sentinel 与 Hystrix 的对比.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/04 Sentinel 基于滑动窗口的实时指标数据统计.md.html">04 Sentinel 基于滑动窗口的实时指标数据统计.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/05 Sentinel 的一些概念与核心类介绍.md.html">05 Sentinel 的一些概念与核心类介绍.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/06 Sentinel 中的责任链模式与 Sentinel 的整体工作流程.md.html">06 Sentinel 中的责任链模式与 Sentinel 的整体工作流程.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/07 Java SPI 及 SPI 在 Sentinel 中的应用.md.html">07 Java SPI 及 SPI 在 Sentinel 中的应用.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/08 资源指标数据统计的实现全解析(上).md.html">08 资源指标数据统计的实现全解析(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/09 资源指标数据统计的实现全解析(下).md.html">09 资源指标数据统计的实现全解析(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/10 限流降级与流量效果控制器(上).md.html">10 限流降级与流量效果控制器(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/11 限流降级与流量效果控制器(中).md.html">11 限流降级与流量效果控制器(中).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/12 限流降级与流量效果控制器(下).md.html">12 限流降级与流量效果控制器(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/13 熔断降级与系统自适应限流.md.html">13 熔断降级与系统自适应限流.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/14 黑白名单限流与热点参数限流.md.html">14 黑白名单限流与热点参数限流.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/15 自定义 ProcessorSlot 实现开关降级.md.html">15 自定义 ProcessorSlot 实现开关降级.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/16 Sentinel 动态数据源:规则动态配置.md.html">16 Sentinel 动态数据源:规则动态配置.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/17 Sentinel 主流框架适配.md.html">17 Sentinel 主流框架适配.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/18 Sentinel 集群限流的实现(上).md.html">18 Sentinel 集群限流的实现(上).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/19 Sentinel 集群限流的实现(下).md.html">19 Sentinel 集群限流的实现(下).md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
<a class="current-tab" href="/专栏/深入理解 Sentinel(完)/20 结束语:Sentinel 对应用的性能影响如何?.md.html">20 结束语:Sentinel 对应用的性能影响如何?.md.html</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="/专栏/深入理解 Sentinel(完)/21 番外篇:Sentinel 1.8.0 熔断降级新特性解读.md.html">21 番外篇:Sentinel 1.8.0 熔断降级新特性解读.md.html</a>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||||
|
||||
<div class="sidebar-toggle-inner"></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function add_inner() {
|
||||
@@ -347,9 +200,6 @@
|
||||
inner.classList.add('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function remove_inner() {
|
||||
|
||||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||||
@@ -357,9 +207,6 @@
|
||||
inner.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sidebar_toggle() {
|
||||
|
||||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||||
@@ -389,9 +236,6 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function open_sidebar() {
|
||||
|
||||
let sidebar = document.querySelector('.book-sidebar')
|
||||
@@ -415,13 +259,7 @@ function hide_canvas() {
|
||||
overlay.classList.remove('show')
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<div class="off-canvas-content">
|
||||
|
||||
<div class="columns">
|
||||
@@ -511,9 +349,6 @@ function hide_canvas() {
|
||||
}
|
||||
|
||||
return chain;
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>Sentinel 使用 Map 而非 ConcurrentMap 是为了尽量避免加锁,大多数场景都是读多写少,以上面代码为例,ProcessorSlotChain 的新增只在资源第一次被访问时,例如接口第一次被调用,而后续都不会再写。假设有 10 个接口,这 10 个接口在应用启动起来就都被访问过了,那么这个 Map 后续就不会再出现写的情况,既然不会再有写操作,就没有必须加锁了,所以使用 Map 而不是使用 ConcurrentMap。</p>
|
||||
@@ -557,9 +392,6 @@ function hide_canvas() {
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>注:1.23 版本是 JMH 目前最新的版本。</p>
|
||||
@@ -573,9 +405,6 @@ function hide_canvas() {
|
||||
<p>@Benchmark 注解用于声明一个 public 方法为基准测试方法,如下代码所示。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -585,13 +414,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p><strong>@BenchmarkMode</strong></p>
|
||||
@@ -599,9 +422,6 @@ function hide_canvas() {
|
||||
<p>通过 JMH 我们可以轻松的测试出某个接口的吞吐量、平均执行时间等指标的数据。假设我们想测试某个方法的平均耗时,那么可以使用 @BenchmarkMode 注解指定测试维度为 Mode.AverageTime,代码如下。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
|
||||
@Benchmark
|
||||
@@ -613,13 +433,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p><strong>@Measurement</strong></p>
|
||||
@@ -627,9 +441,6 @@ function hide_canvas() {
|
||||
<p>假设我们需要测量五次,那么可以使用 @Measurement 注解,代码如下。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@@ -643,13 +454,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>@Measurement 注解有三个配置项:</p>
|
||||
@@ -667,9 +472,6 @@ function hide_canvas() {
|
||||
<p>为了数据准确,我们可能需要让被测试的方法做下热身运动,一定的预热次数可提升测试结果的准备度。可使用 @Warmup 注解声明需要预热的次数、每次预热的持续时间,代码如下。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
|
||||
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
@@ -685,13 +487,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>@Warmup 注解有三个配置项:</p>
|
||||
@@ -713,9 +509,6 @@ function hide_canvas() {
|
||||
<p>如果方法执行耗时为毫秒级别,为了便于观察结果,我们可以使用 @OutputTimeUnit 指定输出的耗时时间单位为毫秒,否则使用默认的秒做单位,会输出 10 的负几次方这样的数字,不太直观。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
|
||||
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
@@ -733,13 +526,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p><strong>@Fork</strong></p>
|
||||
@@ -749,9 +536,6 @@ function hide_canvas() {
|
||||
<p>假设我们不需要多个进程,那么可以使用 @Fork 指定进程数为 1,如下代码所示。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@Fork(1)
|
||||
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@@ -771,13 +555,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p><strong>@Threads</strong></p>
|
||||
@@ -785,9 +563,6 @@ function hide_canvas() {
|
||||
<p>@Threads 注解用于指定使用多少个线程来执行基准测试方法,如果使用 @Threads 指定线程数为 2,那么每次测量都会创建两个线程来执行基准测试方法。</p>
|
||||
|
||||
<pre><code class="language-java">public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@Threads(2)
|
||||
|
||||
@Fork(1)
|
||||
@@ -807,13 +582,7 @@ function hide_canvas() {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>如果 @Measurement 注解指定 time 为 1s,基准测试方法的执行耗时为 1s,那么如果只使用单个线程,一次测量只会执行一次基准测试方法,如果使用 10 个线程,一次测量就能执行 10 次基准测试方法。</p>
|
||||
@@ -835,9 +604,6 @@ function hide_canvas() {
|
||||
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
|
||||
public class MyTestBenchmark {
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -847,9 +613,6 @@ public class MyTestBenchmark {
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -861,9 +624,6 @@ public class MyTestBenchmark {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>下面我们以测试 Gson、Jackson 两个 JSON 解析框架的性能对比为例。</p>
|
||||
@@ -883,15 +643,9 @@ public class MyTestBenchmark {
|
||||
@State(Scope.Benchmark)
|
||||
|
||||
public class JsonBenchmark {
|
||||
|
||||
|
||||
|
||||
private GsonParser gsonParser = new GsonParser();
|
||||
|
||||
private JacksonParser jacksonParser = new JacksonParser();
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -901,9 +655,6 @@ public class JsonBenchmark {
|
||||
gsonParser.fromJson("{\"startDate\":\"2020-04-01 16:00:00\",\"endDate\":\"2020-05-20 13:00:00\",\"flag\":true,\"threads\":5,\"shardingIndex\":0}", JsonTestModel.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -915,9 +666,6 @@ public class JsonBenchmark {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>我们可以使用 @State 注解指定 gsonParser、jacksonParser 这两个字段的共享域。</p>
|
||||
@@ -941,15 +689,9 @@ public class JsonBenchmark {
|
||||
@State(Scope.Thread)
|
||||
|
||||
public class JsonBenchmark {
|
||||
|
||||
|
||||
|
||||
private GsonParser gsonParser = new GsonParser();
|
||||
|
||||
private JacksonParser jacksonParser = new JacksonParser();
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -961,9 +703,6 @@ public class JsonBenchmark {
|
||||
gsonParser.fromJson("{\"startDate\":\"2020-04-01 16:00:00\",\"endDate\":\"2020-05-20 13:00:00\",\"flag\":true,\"threads\":5,\"shardingIndex\":0}", JsonTestModel.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -975,9 +714,6 @@ public class JsonBenchmark {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>执行 testGson 方法输出的结果如下:</p>
|
||||
@@ -999,9 +735,6 @@ current Thread:com.msyc.common.JsonBenchmark.testGson-jmh-worker-1==>20636847
|
||||
current Thread:com.msyc.common.JsonBenchmark.testGson-jmh-worker-2==>1629232880
|
||||
|
||||
......
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p><strong>@Param</strong></p>
|
||||
@@ -1025,15 +758,9 @@ current Thread:com.msyc.common.JsonBenchmark.testGson-jmh-worker-2==>16292328
|
||||
@State(Scope.Thread)
|
||||
|
||||
public class JsonBenchmark {
|
||||
|
||||
|
||||
|
||||
private GsonParser gsonParser = new GsonParser();
|
||||
|
||||
private JacksonParser jacksonParser = new JacksonParser();
|
||||
|
||||
|
||||
|
||||
// 指定参数有三个值
|
||||
|
||||
@Param(value =
|
||||
@@ -1045,9 +772,6 @@ public class JsonBenchmark {
|
||||
"{\"flag\":true,\"threads\":5,\"shardingIndex\":0}"})
|
||||
|
||||
private String jsonStr;
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -1057,9 +781,6 @@ public class JsonBenchmark {
|
||||
gsonParser.fromJson(jsonStr, JsonTestModel.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Test
|
||||
@@ -1069,13 +790,7 @@ public class JsonBenchmark {
|
||||
jacksonParser.fromJson(jsonStr, JsonTestModel.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>测试结果如下:</p>
|
||||
@@ -1083,29 +798,11 @@ public class JsonBenchmark {
|
||||
<pre><code class="language-text">Benchmark (jsonStr) Mode Cnt Score Error Units
|
||||
|
||||
JsonBenchmark.testGson {"startDate":"2020-04-01 16:00:00","endDate":"2020-05-20 13:00:00","flag":true,"threads":5,"shardingIndex":0} avgt 5 12180.763 ± 2481.973 ns/op
|
||||
|
||||
|
||||
|
||||
JsonBenchmark.testGson {"startDate":"2020-04-01 16:00:00","endDate":"2020-05-20 14:00:00"} avgt 5 8154.709 ± 3393.881 ns/op
|
||||
|
||||
|
||||
|
||||
JsonBenchmark.testGson {"flag":true,"threads":5,"shardingIndex":0} avgt 5 9994.171 ± 5737.958 ns/op
|
||||
|
||||
|
||||
|
||||
JsonBenchmark.testJackson {"startDate":"2020-04-01 16:00:00","endDate":"2020-05-20 13:00:00","flag":true,"threads":5,"shardingIndex":0} avgt 5 15663.060 ± 9042.672 ns/op
|
||||
|
||||
|
||||
|
||||
JsonBenchmark.testJackson {"startDate":"2020-04-01 16:00:00","endDate":"2020-05-20 14:00:00"} avgt 5 13776.828 ± 11006.412 ns/op
|
||||
|
||||
|
||||
|
||||
JsonBenchmark.testJackson {"flag":true,"threads":5,"shardingIndex":0} avgt 5 9824.283 ± 311.555 ns/op
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h4><strong>非注解方式使用</strong></h4>
|
||||
@@ -1115,9 +812,6 @@ JsonBenchmark.testJackson
|
||||
<p>使用非注解方式实现上面的例子,代码如下。</p>
|
||||
|
||||
<pre><code class="language-java">public class BenchmarkTest{
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
|
||||
public void test() throws RunnerException {
|
||||
@@ -1149,13 +843,7 @@ JsonBenchmark.testJackson
|
||||
new Runner(options).run();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<ul>
|
||||
@@ -1175,9 +863,6 @@ JsonBenchmark.testJackson
|
||||
<p>使用 Java 命令即可运行一个基准测试应用:</p>
|
||||
|
||||
<pre><code class="language-shell">java -jar my-benchmarks.jar
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h4>在 IDEA 中执行</h4>
|
||||
@@ -1185,9 +870,6 @@ JsonBenchmark.testJackson
|
||||
<p>在 IDEA 中,我们可以编写一个单元测试方法,在单元测试方法中创建一个 org.openjdk.jmh.runner.Runner,调用 Runner 的 run 方法执行基准测试。但 JMH 不会去扫描包,不会执行每个基准测试方法,这需要我们通过配置项来告知 JMH 需要执行哪些基准测试方法。</p>
|
||||
|
||||
<pre><code class="language-java">public class BenchmarkTest{
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
|
||||
public void test() throws RunnerException {
|
||||
@@ -1197,13 +879,7 @@ JsonBenchmark.testJackson
|
||||
new Runner(options).run();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>完整例子如下:</p>
|
||||
@@ -1227,9 +903,6 @@ JsonBenchmark.testJackson
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>Options 在前面已经介绍过了,由于本例中 JsonBenchmark 这个类已经使用了注解,因此 Options 只需要配置需要执行基准测试的类。如果需要执行多个基准测试类,include 方法可以多次调用。如果需要将测试结果输出到文件,可调用 output 方法配置文件路径,不配置则输出到控制台。</p>
|
||||
@@ -1271,17 +944,11 @@ JsonBenchmark.testJackson
|
||||
@State(Scope.Thread)
|
||||
|
||||
public class SentinelEntryBenchmark {
|
||||
|
||||
|
||||
|
||||
@Param({"25", "50", "100", "200", "500", "1000"})
|
||||
|
||||
private int length;
|
||||
|
||||
private List<Integer> numbers;
|
||||
|
||||
|
||||
|
||||
@Setup
|
||||
|
||||
public void prepare() {
|
||||
@@ -1295,9 +962,6 @@ public class SentinelEntryBenchmark {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Threads(8)
|
||||
@@ -1309,9 +973,6 @@ public class SentinelEntryBenchmark {
|
||||
Collections.sort(numbers);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Benchmark
|
||||
|
||||
@Threads(8)
|
||||
@@ -1339,13 +1000,7 @@ public class SentinelEntryBenchmark {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>该基准测试类使用 @State 指定每个线程使用不同的 numbers 字段的实例,所以 @Setup 注解的方法也会执行 8 次,分别是在每个线程开始执行基准测试方法之前执行,用于完成初始化工作,与 Junit 中的 @Before 注解功能相似。</p>
|
||||
@@ -1361,9 +1016,6 @@ public class SentinelEntryBenchmark {
|
||||
(min, avg, max) = (295869.456, 300948.682, 316089.624), stdev = 8631.655
|
||||
|
||||
CI (99.9%): [267711.254, 334186.110] (assumes normal distribution)
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>最小 ops/s 为 295869.456,平均 ops/s 为 300948.682,最大 ops/s 为 316089.624。</p>
|
||||
@@ -1377,9 +1029,6 @@ public class SentinelEntryBenchmark {
|
||||
(min, avg, max) = (280835.799, 309934.827, 337712.803), stdev = 25686.753
|
||||
|
||||
CI (99.9%): [211024.287, 408845.366] (assumes normal distribution)
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
||||
<p>最小 ops/s 为 280835.799,平均 ops/s 为 309934.827,最大 ops/s 为 337712.803。</p>
|
||||
@@ -1419,9 +1068,6 @@ public class SentinelEntryBenchmark {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1429,9 +1075,6 @@ public class SentinelEntryBenchmark {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||||
|
||||
</div>
|
||||
@@ -1447,17 +1090,11 @@ public class SentinelEntryBenchmark {
|
||||
<script>
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
|
||||
|
||||
function gtag() {
|
||||
|
||||
dataLayer.push(arguments);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-NPSEEVD756');
|
||||
@@ -1483,9 +1120,6 @@ public class SentinelEntryBenchmark {
|
||||
setCookie("lastPath", path)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setCookie(cname, cvalue) {
|
||||
|
||||
var d = new Date();
|
||||
@@ -1497,9 +1131,6 @@ public class SentinelEntryBenchmark {
|
||||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getCookie(cname) {
|
||||
|
||||
var name = cname + "=";
|
||||
@@ -1517,12 +1148,6 @@ public class SentinelEntryBenchmark {
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</html>
|
||||
|
||||
|
Reference in New Issue
Block a user