PageSourceSearch

http://ibeetl.com/assets/index.html-Dil5py-4.js

js ibeetl.com collected 2026-09-25 20:04:35 UTC 38,009 bytes, 88 lines download raw bytes

1import{_ as i,c as a,b as n,o as l}from"./app-B8MQJI6s.js";const t="/assets/cacheline_1-CMAaeKyY.png",e="/assets/cacheline_2-Pb-dlcJ5.png",p={};function h(k,s){return l(),a("div",null,s[0]||(s[0]=[n(`<h2 id="_6-13-缓存伪共享" tabindex="-1"><a class="header-anchor" href="#_6-13-缓存伪共享"><span>6.13 缓存伪共享</span></a></h2><p>现代计算机,CPU的运行速度与从内存加载数据速度有着较大鸿沟,比如CPU从寄存器加载数据需要1纳秒时间,而从内存中需要100纳秒。因此CPU使用缓存技术,预先加载可能访问的数据到CPU的缓存里以提高性能。这些数据可能是</p><ul><li>上一次访问的数据,推测下一次可能会接着访问,保留在CPU缓存里</li><li>连续存储的数据,如数组,或者对象的各个字段一次性加载到缓存</li></ul><p>CPU是通过缓存行<code>Cache Line</code>作为最小操作单位,缓存行通常64字节或者128字节大小。对于如下类,变量count和index有可能同时被加载到缓存行</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> static</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994;"> DataWithoutPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span></span>
2<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    volatile</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> count</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
3<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    volatile</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> index</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
4<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>或者DataWithoutPadding[]中的连续存储的2个元素,类似如下</p><p><img src="`+t+'" alt=""></p><p>在多CPU架构下,多个CPU都缓存了DataWithoutPadding[0],当一个CPU修改DataWithoutPadding[0].count时候,其他CPU的缓存DataWithoutPadding[0].count将被通知为无效,如果需要操作count,则需要再从主内存中加载最新值,相比于直接从CPU缓存取值,性能降低了1-2各数量级</p><p>即使其他CPU没有操作count,操作的是缓存行中的index,但因为CPU是以Cache Line为最小操作单位,实际上其他CPU缓存中的index仍然被通知无效,还是需要从主存中加载</p><p>关键字volatile保证了其值的多CPU的可见性</p><p>伪共享问题是因为缓存行的某个缓存无效(如count),导致这个缓存行的其他缓存值(index)在其他CPU中变得无效</p><p>
4解决这个伪共享问题通常使用填充技术,保证当前64字节的缓存行只有count变量或者只有index变量。如下图</p><p><img src="'+e+`" alt=""></p><p>这样,当CPU0的index修改的时候,CPU1的缓存行因为没有index变量,只有count变量,可以使得count变量在缓存中被CPU1使用。而不必从主内存加载。</p><p>早期填充方法是在同一个类里,申明无意义的多个变量,比如对于count,可以前后填充</p><div class="language-c++ line-numbers-mode" data-ext="c++" data-title="c++"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span>/*</span></span>
5<span class="line"><span>https://developer.aliyun.com/article/1727112#1</span></span>
6<span class="line"><span>*/</span></span>
7<span class="line"><span>public class ManualPaddingLong {</span></span>
8<span class="line"><span>    /**</span></span>
9<span class="line"><span>     * 前填充:7个long类型变量,共56字节,避免目标变量与对象头、前序变量共享缓存行</span></span>
10<span class="line"><span>     */</span></span>
11<span class="line"><span>    private volatile long p1, p2, p3, p4, p5, p6, p7;</span></span>
12<span class="line"><span>    /**</span></span>
13<span class="line"><span>     * 目标变量,被多线程频繁修改的热点变量</span></span>
14<span class="line"><span>     */</span></span>
15<span class="line"><span>    public volatile long count;</span></span>
16<span class="line"><span></span></span>
17<span class="line"><span>    /**</span></span>
18<span class="line"><span>     * 后填充:7个long类型变量,共56字节,避免目标变量与后序变量共享缓存行,同时应对CPU相邻缓存行预取</span></span>
19<span class="line"><span>     */</span></span>
20<span class="line"><span>    private volatile long q1, q2, q3, q4, q5, q6, q7;</span></span>
21<span class="line"><span></span></span>
22<span class="line"><span>    /**</span></span>
23<span class="line"><span>
23     * 访问填充字段,避免JIT编译器将其优化消除</span></span>
24<span class="line"><span>     * @return 填充字段的求和结果,无实际业务意义</span></span>
25<span class="line"><span>     */</span></span>
26<span class="line"><span>    public long avoidJitOptimize() {</span></span>
27<span class="line"><span>        return p1 + p2 + p3 + p4 + p5 + p6 + p7 + q1 + q2 + q3 + q4 + q5 + q6 + q7;</span></span>
28<span class="line"><span>    }</span></span>
29<span class="line"><span>}</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Java8后,可以使用@Contended,Java将在运行时候自动完成填充,@Contended可以应用在字段或者整个类上,Java高并发代码,如LongAdder.Cell,ConcurrentHashMap.CounterCell 使用此注解完成自动填充.如下是CounterCell实现</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">@</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">jdk</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">internal</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">vm</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">annotation</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">Contended</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> static</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> final</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994;"> CounterCell</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span></span>
30<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    volatile</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> value</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
31<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">    CounterCell</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">long</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> x</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> value </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> x</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> }</span></span>
32<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>本书例子<code>CPUCacheLIneTest</code> 比较了使用Contended的性能,</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">@</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">jdk</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">
32internal</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">vm</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">annotation</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">Contended</span></span>
33<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> static</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994;"> Data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">{</span></span>
34<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    volatile</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> count</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
35<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> addCount</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
36<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        count</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">++</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
37<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> count</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
38<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
39<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span>
40<span class="line"></span>
41<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> static</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994;"> DataWithoutPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span></span>
42<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    volatile</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> count</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
43<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> long</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> addCount</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
44<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">        count</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">++</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
45<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> count</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">;</span></span>
46<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
47<span class="line"></span>
48<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>注意,jdk.internal.vm.annotation.Contended注解被移到了<code>jdk.internal.vm.annotation</code>包中,归属<code>java.base</code>模块,默认不对外导出,需要在编译的时候显示<code>--add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED</code></p><p>JMH测试代码如下</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">@</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Fork</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;">value</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;"> 1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#A65E2B;--shiki-dark:#C99076;"> jvmArgsPrepend</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span></span>
49<span class="line"><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">        &quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">-XX:-RestrictContended</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span></span>
50<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">})</span></span>
51<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994;"> CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> {</span></span>
52<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">    //连续存储</span></span>
53<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    Data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[]</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> datas</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;"> new</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> Data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[]{</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">new</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> Data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(),</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">new</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> Data</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">()};</span></span>
54<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    DataWithoutPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[]</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> dataWithoutPaddings</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;"> new</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> DataWithoutPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[]{</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">new</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> DataWithoutPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(),</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">new</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> DataWithoutPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">()};</span></span>
55<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Benchmark</span></span>
56<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Group</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">fill</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
57<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">GroupThreads</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
58<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">  long</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">  dataCount</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
59<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> datas</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">0</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">].</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">addCount</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">();</span></span>
60<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
61<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Group</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">fill</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
62<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">GroupThreads</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
63<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Benchmark</span></span>
64<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">  long</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">  dataCount2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
65<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> datas</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">].</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">addCount</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">();</span></span>
66<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
67<span class="line"></span>
68<span class="line"></span>
69<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Group</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">unfill</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
70<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">GroupThreads</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
71<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Benchmark</span></span>
72<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">  long</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">  dataCountNoPadding</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
73<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> dataWithoutPaddings</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">0</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">].</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">addCount</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">();</span></span>
74<span class="line"></span>
75<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
76<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Group</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">unfill</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
77<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">GroupThreads</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">)</span></span>
78<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    @</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">Benchmark</span></span>
79<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    public</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">  long</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">  dataCountNoPadding2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
80<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        return</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> dataWithoutPaddings</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">].</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">addCount
80</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">();</span></span>
81<span class="line"></span>
82<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
83<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">   }</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这段JMH代码解释如下</p><table><thead><tr><th style="text-align:left;">注解</th><th style="text-align:left;">说明</th></tr></thead><tbody><tr><td style="text-align:left;">@Group</td><td style="text-align:left;">对测试方法分组,本例子分为fill和unfill俩组。每组都有俩个方法调用,分别修改连续数组中的俩个值,以模拟伪共享问题</td></tr><tr><td style="text-align:left;">@GroupThreads(1)</td><td style="text-align:left;">测试方法所在组使用的线程数,这里设定1个线程</td></tr><tr><td style="text-align:left;">-XX:-RestrictContended</td><td style="text-align:left;">JVM必须使用此配置,开启JVM自动填充生效。</td></tr></tbody></table><p>JMH测试结果如下,可以看缓存行填充的吞吐量是2倍于无填充的场景</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">fill</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">                        thrpt   </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">10</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">  85953.571</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> ± </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">4483.237</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">  ops</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">/</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">ms</span></span>
84<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">fill</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">dataCount              thrpt   </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">10</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">  43462.344</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> ± </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">2200.061</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">  ops</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">/</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">ms</span></span>
85<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">fill</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">dataCount2             thrpt   </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">10</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">  42491.227</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> ± </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">
852325.268</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">  ops</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">/</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">ms</span></span>
86<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">unfill</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">                      thrpt   </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">10</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">  51176.091</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> ± </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">3016.431</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">  ops</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">/</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">ms</span></span>
87<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">unfill</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">dataCountNoPadding   thrpt   </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">10</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">  25595.354</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> ± </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1539.592</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">  ops</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">/</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">ms</span></span>
88<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">CPUCacheLIneTest2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">unfill</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">:</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">dataCountNoPadding2  thrpt   </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">10</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">  25580.737</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> ± </span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1501.565</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">  ops</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">/</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">ms</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>关于<code>@Contended</code> ,请参考JEP 142: Reduce Cache Contention on Specified Fields,即“减少指定字段上的缓存争用”</p>`,28)]))}const r=i(p,[["render",h],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/article/performance/microtuning_falseshare/","title":"性能微优化-缓存伪共享","lang":"en-US","frontmatter":{"title":"性能微优化-缓存伪共享","tags":["性能","新书"],"createTime":"2026/08/20 9:45:15","permalink":"/article/performance/microtuning_falseshare/","description":"6.13 缓存伪共享 现代计算机,CPU的运行速度与从内存加载数据速度有着较大鸿沟,比如CPU从寄存器加载数据需要1纳秒时间,而从内存中需要100纳秒。因此CPU使用缓存技术,预先加载可能访问的数据到CPU的缓存里以提高性能。这些数据可能是 上一次访问的数据,推测下一次可能会接着访问,保留在CPU缓存里 连续存储的数据,如数组,或者对象的各个字段一次性...","head":[["meta",{"property":"og:url","content":"http://ibeetl.com/article/performance/microtuning_falseshare/"}],["meta",{"property":"og:site_name","content":"闲大赋"}],["meta",{"property":"og:title","content":"性能微优化-缓存伪共享"}],["meta",{"property":"og:description","content":"6.13 缓存伪共享 现代计算机,CPU的运行速度与从内存加载数据速度有着较大鸿沟,比如CPU从寄存器加载数据需要1纳秒时间,而从内存中需要100纳秒。因此CPU使用缓存技术,预先加载可能访问的数据到CPU的缓存里以提高性能。这些数据可能是 上一次访问的数据,推测下一次可能会接着访问,保留在CPU缓存里 连续存储的数据,如数组,或者对象的各个字段一次性..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2026-08-21T06:57:39.000Z"}],["meta",{"property":"article:tag","content":"性能"}],["meta",{"property":"article:tag","content":"新书"}],["meta",{"property":"article:modified_time","content":"2026-08-21T06:57:39.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"性能微优化-缓存伪共享\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"202
886-08-21T06:57:39.000Z\\",\\"author\\":[]}"]]},"headers":[],"readingTime":{"minutes":4.09,"words":1226},"git":{"updatedTime":1787295459000,"contributors":[{"name":"lijiazhi","username":"lijiazhi","email":"[email protected]","commits":1,"avatar":"https://gravatar.com/avatar/1b5114831459724ad4acc394423b4b48ecfa4a7e0659fbe07a0ce5181a1050a7?d=retro"}]},"autoDesc":true,"filePathRelative":"article/性能/false_share.md","categoryList":[{"id":"92a2b5","sort":10001,"name":"article"},{"id":"afdb50","sort":10003,"name":"性能"}]}');export{r as comp,g as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.