Java:使用SingletonStream获得性能
僅具有一個(gè)元素的Java流有時(shí)會(huì)在應(yīng)用程序中造成不必要的開銷。 了解如何使用SingletonStream對(duì)象并為其中某些此類流獲得十倍的性能,并了解如何同時(shí)簡(jiǎn)化代碼。
背景
Java 8中的Stream庫(kù)是有史以來(lái)Java語(yǔ)言最強(qiáng)大的功能之一。 一旦您開始了解它的多功能性和所產(chǎn)生的代碼可讀性,您的Java代碼樣式將永遠(yuǎn)改變。 與其使用for , if和switch語(yǔ)句以及眾多中間變量來(lái)充斥所有瑣碎的細(xì)節(jié),您還可以使用Stream ,它僅包含要做什么的描述,而不是實(shí)際上是如何完成的。
幾年前,我們不得不為Java項(xiàng)目做出API決定:我們應(yīng)該為兩種快速本地內(nèi)存數(shù)據(jù)緩存方法選擇哪種返回類型;
- 唯一的搜索鍵,返回一個(gè)值或不返回任何值
- 一個(gè)非唯一的搜索鍵,它返回任意數(shù)量的值(零到無(wú)窮大)。
這是最初的想法:
Optional<T> searchUnique(K key); // For unique keys Stream<T> search(K key);? ? ? ? ?// For non-unique keys 但是,我們希望這兩個(gè)方法看起來(lái)完全相同,并且都返回一個(gè)
Stream<T> 。 然后,API看起來(lái)會(huì)更加整潔,因?yàn)槲ㄒ痪彺鎸⒖瓷先ヅc非唯一緩存完全相同。
但是,唯一搜索必須非常高效,并且每秒必須創(chuàng)建數(shù)百萬(wàn)個(gè)結(jié)果對(duì)象,而又不會(huì)產(chǎn)生太多開銷。
解決方案
通過(guò)實(shí)現(xiàn)僅包含單個(gè)元素的SingletonStream (因此,與具有任意數(shù)量元素的普通Stream相比,可以進(jìn)行高度優(yōu)化),我們能夠讓這兩種方法在保持性能的同時(shí)返回Stream 。 如果未找到鍵,則方法searchUnique(K key)將返回一個(gè)空流( Stream.empty() ),如果該鍵存在,則它將返回SingletonStream以及與該鍵關(guān)聯(lián)的值。 我們會(huì)得到:
Stream<T> searchUnique(K key); // For unique keys Stream<T> search(K key); // For non-unique keys大! 我們可以吃餅干,仍然可以吃!
實(shí)施
SingletonStream是Speedment Stream ORM的一部分,可以在GitHub上查看。 隨意使用的Speedment自己的項(xiàng)目中使用Speedment任何它的組件的初始化 。
SingletonStream是使用JVM的Escape Analysis進(jìn)行堆棧分配的不錯(cuò)選擇(在我以前的文章中, 這里和此處有關(guān)Escape Analysis的更多信息 )。 該實(shí)現(xiàn)有兩種形式。 如果將STRICT值設(shè)置為true ,我們將獲得一個(gè)完全惰性的Stream ,但是缺點(diǎn)是,一旦調(diào)用諸如.filter(), map()等中間操作 ,我們將失去Singleton屬性 。另一方面,將STRICT值設(shè)置為false , SingletonStream會(huì)急切地執(zhí)行許多中間操作 ,并且它將能夠返回新的SingletonStream從而保留Singleton屬性 。 在許多情況下,這將提供更好的性能。
這里為參考流設(shè)計(jì)的解決方案也可以很容易地修改為單例流的原始形式。 因此,編寫SingletonIntStream ,
SingletonLongStream和SingletonDoubleStream 。 這是SingletonLongStream 。
應(yīng)該注意的是,該類可以進(jìn)一步發(fā)展,以便它可以支持惰性評(píng)估,同時(shí)始終保持高性能。 這是未來(lái)的工作。
性能
有多種方法可以測(cè)試SingletonStream的性能,并將其與具有一個(gè)元素的標(biāo)準(zhǔn)Stream實(shí)現(xiàn)進(jìn)行比較。
這是使用JMH的一種方法。 第一個(gè)測(cè)試(計(jì)數(shù))僅對(duì)流中的元素?cái)?shù)進(jìn)行計(jì)數(shù),第二個(gè)測(cè)試(forEach)對(duì)流中的一個(gè)元素執(zhí)行某些操作。
@Benchmark public long singletonStreamCount() {return SingletonStream.of("A").count(); }@Benchmark public long streamCount() {return Stream.of("A").count(); }@Benchmark public void singletonStreamForEach() {SingletonStream.of("A").limit(1).forEach(blackHole()); }@Benchmark public void streamForEach() {Stream.of("A").limit(1).forEach(blackHole()); }private static <T> Consumer<T> blackHole() {return t -> {}; }在MacBook Pro筆記本電腦上運(yùn)行時(shí),將產(chǎn)生以下結(jié)果:
... Benchmark Mode Cnt Score Error Units SingletonBench.singletonStreamCount thrpt 333419753.335 ops/s SingletonBench.singletonStreamForEach thrpt 2312262034.214 ops/s SingletonBench.streamCount thrpt 27453782.595 ops/s SingletonBench.streamForEach thrpt 26156364.956 ops/s ...“計(jì)數(shù)”操作的加速因子超過(guò)10。 對(duì)于“ forEach”操作,看來(lái)JVM能夠完全優(yōu)化SingletonStream的完整代碼路徑。
測(cè)試一下
使用Speedment 初始化程序下載Speedment。
完整的測(cè)試課程在這里可用。
結(jié)論
SingletonStream或多或少地作為擴(kuò)展的Optional起作用,并在保持Stream庫(kù)優(yōu)點(diǎn)的同時(shí)提供高性能。
您可以通過(guò)將STRICT值設(shè)置為首選的嚴(yán)格性/性能選擇來(lái)選擇它的兩個(gè)版本。
SingletonStream可以進(jìn)一步改進(jìn)。
翻譯自: https://www.javacodegeeks.com/2018/10/java-gain-performance-singletonstream.html
總結(jié)
以上是生活随笔為你收集整理的Java:使用SingletonStream获得性能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: tomcat 正常关闭_Tomcat的带
- 下一篇: java中方法的命名_Java方法中的参