簡體   English   中英

Java無鎖性能JMH

[英]Java lock-free performance JMH

我有一個JMH多線程測試:

@State(Scope.Benchmark)
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Fork(value = 1, jvmArgsAppend = { "-Xmx512m", "-server", "-XX:+AggressiveOpts","-XX:+UnlockDiagnosticVMOptions",
        "-XX:+UnlockExperimentalVMOptions", "-XX:+PrintAssembly", "-XX:PrintAssemblyOptions=intel",
        "-XX:+PrintSignatureHandlers"})
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
public class LinkedQueueBenchmark {
private static final Unsafe unsafe = UnsafeProvider.getUnsafe();
private static final long offsetObject;
private static final long offsetNext;

private static final int THREADS = 5;
private static class Node {
    private volatile Node next;
    public Node() {}
}

static {
    try {
        offsetObject = unsafe.objectFieldOffset(LinkedQueueBenchmark.class.getDeclaredField("object"));
        offsetNext = unsafe.objectFieldOffset(Node.class.getDeclaredField("next"));
    } catch (Exception ex) { throw new Error(ex); }
}

protected long t0,t1,t2,t3,t4,t5,t6,t7;
private volatile Node object = new Node(null);


@Threads(THREADS)
@Benchmark
public Node doTestCasSmart() {
    Node current, o = new Node();
    for(;;) {
        current = this.object;
        if (unsafe.compareAndSwapObject(this, offsetObject, current, o)) {
            //current.next = o; //Special line:
            break;
        } else {
            LockSupport.parkNanos(1);
        }
    }
    return current;
}
}
  1. 在當前版本中,我的性能約為55 ops / us
  2. 但是,如果我取消注釋“特殊行”,或將其替換為unsafe.putOrderedObject(在任何方向上-current.next = oo.next = current ),性能約為2 ops / us。

據我了解,這與CPU緩存有關,也許正在清除存儲緩沖區。 如果我確實將其替換為沒有CAS的基於鎖的方法,性能將為11-20 ops / us。
我嘗試使用LinuxPerfAsmProfiler和PrintAssembly,在第二種情況下,我看到:

....[Hottest Regions]...............................................................................
 25.92%   17.93%  [0x7f1d5105fe60:0x7f1d5105fe69] in SpinPause (libjvm.so)
 17.53%   20.62%  [0x7f1d5119dd88:0x7f1d5119de57] in ParMarkBitMap::live_words_in_range(HeapWord*, oopDesc*) const (libjvm.so)
 10.81%    6.30%  [0x7f1d5129cff5:0x7f1d5129d0ed] in ParallelTaskTerminator::offer_termination(TerminatorTerminator*) (libjvm.so)
  7.99%    9.86%  [0x7f1d3c51d280:0x7f1d3c51d3a2] in com.jad.generated.LinkedQueueBenchmark_doTestCasSmart::doTestCasSmart_thrpt_jmhStub 

有人可以向我解釋實際情況嗎? 為什么這么慢? 哪里有儲物障礙? 為什么putOrdered不起作用? 以及如何解決?

規則:您應該首先尋找愚蠢的錯誤,而不是尋找“高級”答案。

SpinPauseParMarkBitMap::live_words_in_range(HeapWord*, oopDesc*)ParallelTaskTerminator::offer_termination(TerminatorTerminator*)來自GC線程。 這很可能意味着大多數工作基准確實是GC。 確實,運行不帶-prof gc注釋的“特殊行”將產生:

# Run complete. Total time: 00:00:43

Benchmark                      Mode  Cnt      Score    Error   Units
LQB.doTestCasSmart            thrpt    5      5.930 ±  3.867  ops/us
LQB.doTestCasSmart:·gc.time   thrpt    5  29970.000               ms

因此,在運行的43秒中,您花費了30秒來進行GC。 或者,即使是普通的-verbose:gc也會顯示它:

Iteration   3: [Full GC (Ergonomics)  408188K->1542K(454656K), 0.0043022 secs]
[GC (Allocation Failure)  60422K->60174K(454656K), 0.2061024 secs]
[GC (Allocation Failure)  119054K->118830K(454656K), 0.2314572 secs]
[GC (Allocation Failure)  177710K->177430K(454656K), 0.2268396 secs]
[GC (Allocation Failure)  236310K->236054K(454656K), 0.1718049 secs]
[GC (Allocation Failure)  294934K->294566K(454656K), 0.2265855 secs]
[Full GC (Ergonomics)  294566K->147408K(466432K), 0.7139546 secs]
[GC (Allocation Failure)  206288K->205880K(466432K), 0.2065388 secs]
[GC (Allocation Failure)  264760K->264312K(466432K), 0.2314117 secs]
[GC (Allocation Failure)  323192K->323016K(466432K), 0.2183271 secs]
[Full GC (Ergonomics)  323016K->322663K(466432K), 2.8058725 secs]

2.8s完整的GC,真糟。 在GC中花費大約5s,在一次迭代中,運行時間為5s。 那也很爛。

為什么? 好吧,您正在此處建立鏈接列表。 當然,隊列的頭是不可訪問的,應該收集從頭到object所有內容。 但是收集不是瞬時的。 隊列越長,消耗的內存越多,GC遍歷它的工作就越多。 這是一個積極的反饋循環,會削弱執行力。 由於隊列元素無論如何都是可收集的,因此此反饋循環永遠不會到達OOME。 將初始object存儲在新的head字段中將最終對OOME進行測試。

因此,坦率地說,您的問題與putOrdered ,內存障礙或隊列性能無關。 我認為您需要重新考慮您實際測試的內容。 設計測試以使每個@Benchmark調用中的瞬態內存占用量保持不變本身就是一門藝術。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM