文章轉自belaban.blogspot.com
Double your performance: virtual threads (fibers) and JDK 15/16!
If you use UDP as transport and want to double your performance: read on!
If you use TCP, your performance won't change much. You might still be interested in what more recent JDKs and virtual threads (used to be called 'fibers') will bring to the table.
Virtual threads
Virtual threads are lightweight threads, similar in concept to the old Green Threads, and are managed by the JVM rather than the kernel. Many virtual threads can map to the same OS native (carrier) thread (only one at a time, of course), so we can have millions of virtual threads.
Virtual threads are implemented with continuations, but that's a detail. What's important is that all blocking calls in the JDK (LockSupport.park() etc) have been modified to yield rather than block. This means that we don't waste the precious native carrier thread, but simply go to a non-RUNNING state. When the block is over, the thread is simply marked as RUNNABLE again and the scheduler continues the continuation where it left off.
Main advantages:
Blocking calls don't need to be changed, e.g. into reactive calls
No need for thread pools: simply create a virtual thread
Fewer context switches (reduced/eliminated blocking calls)
We can have lots of virtual threads
It will be a while until virtual threads show up in your JDK, but JGroups has already added support for it: just set use_fibers="true" in the transport. If the JVM supports virtual threads, they will be used, otherwise we fall back to regular native threads.
UDP: networking improvements
While virtual threads bring advantages to JGroups, the other performance increase can be had by trying a more recent JDK.
Starting in JDK 15, the implementation of DatagramSockets and MulticastSockets has been changed to delegate to DatagramChannels and MulticastChannels. In addition, virtual threads are supported.
This increases the performance of UDP which uses DatagramChannels and MulticastChannels.
The combination of networking code improvements and virtual threads leads to astonishing results for UDP, read below.
Performance
I used UPerf for testing on a cluster of 8 (physical) boxes (1 GBit ethernet), with JDKs 11, 16-ea5 and 16-loom+2-14. The former two use native threads, the latter uses virtual threads.
As can be seen in [1], UDP's performance goes from 44'691 on JDK 11 to 81'402 on JDK 16-ea5; that's a whopping 82% increase! Enabling virtual threads increases the performance between 16-ea5 and 16-loom+2-14 to 88'252, that's another 8%!
The performance difference between JDK 11 and 16-loom is 97%!
The difference in TCP's performance is miniscule; I guess because the TCP code was already optimized in JDK 11.
Running in JDK 16-loom+2-14 shows that UDP's performance is now on par with TCP, as a matter of fact, UDP is even 3% faster than TCP!
If you want to try for yourself: head over to the JGroups Github repo and create the JAR (ant jar). Or wait a bit: I will soon release 5.0.0.Final which contains the changes.
Not sure if I want to backport the changes to the 4.x branch...
Enjoy!
[1] https://drive.google.com/file/d/1Ars1LOM7cEf6AWpPwZHeIfu_kKLa9gv0/view?usp=sharing
[2] http://openjdk.java.net/jeps/373
性能加倍:虛擬線程(光纖)和JDK15/16!
如果您使用UDP作為傳輸,並希望將性能提高一倍:請繼續閱讀!
如果使用TCP,性能不會有太大變化。您可能仍然對最近的jdk和虛擬線程(以前稱為“fibers”)將帶來什么感興趣。
虛擬線程
虛擬線程是輕量級線程,在概念上類似於舊的綠色線程,由JVM而不是內核來管理。許多虛擬線程可以映射到同一個操作系統本機(運營商)線程(當然,一次只能映射一個),因此我們可以擁有數百萬個虛擬線程。
虛擬線程是用continuations實現的,但這只是一個細節。重要的是JDK中的所有阻塞調用(停車場鎖支架()等)已修改為屈服而不是阻塞。這意味着我們不會浪費寶貴的本機載波線程,而只是進入非運行狀態。當塊結束時,線程被簡單地再次標記為可運行,調度程序在它停止的地方繼續繼續執行。
主要優點:
阻塞呼叫不需要更改,例如變為被動呼叫
不需要線程池:只需創建一個虛擬線程
更少的上下文切換(減少/消除阻塞調用)
我們可以有很多虛擬線程
虛擬線程在JDK中出現還需要一段時間,但JGroups已經添加了對它的支持:只需在傳輸中設置use_fibers=“true”。如果JVM支持虛擬線程,那么將使用它們,否則我們將返回到常規的本機線程。
UDP:網絡改進
雖然虛擬線程為jgroup帶來了優勢,但通過嘗試更新的JDK,可以獲得其他性能提升。
從jdk15開始,DatagramSockets和MulticastSockets的實現已經改為委托給DatagramChannels和multicast channels。此外,還支持虛擬線程。
這提高了UDP使用DatagramChannels和multicast channels的性能。
網絡代碼改進和虛擬線程的結合為UDP帶來了驚人的結果,如下所示。
性能
用於以太網測試(1-16個)和1-5個虛擬機的JDEAK(16個)和1個。前兩個使用本機線程,后一個使用虛擬線程。
從[1]中可以看出,UDP的性能從jdk11上的44'691提高到jdk16-ea5上的81'402;這是驚人的82%的增長!啟用虛擬線程可以將16-ea5和16織機+2-14之間的性能提高到88'252,這又是8%!
jdk11和16織機的性能差異是97%!
TCP的性能差別很小;我想是因為TCP代碼已經在jdk11中進行了優化。
在jdk16loom+2-14上運行表明UDP的性能已經與TCP不相上下,事實上UDP甚至比TCP快3%!
如果您想自己嘗試一下:轉到JGroups Github repo並創建JAR(antjar)。或者稍等一下:我很快就會發布5.0.0.Final,其中包含了這些更改。
不確定是否要將更改后傳到4.x分支。。。
享受吧!
[1]https://drive.google.com/file/d/1Ars1LOM7cEf6AWpPwZHeIfu kKLa9gv0/view?usp=分享
[2]http://openjdk.java.net/jeps/373
