Java:使用SingletonStream获得性能
僅具有一個元素的Java流有時會在應用程序中造成不必要的開銷。 了解如何使用SingletonStream對象并為其中某些此類流獲得十倍的性能,并了解如何同時簡化代碼。
背景
Java 8中的Stream庫是有史以來Java語言最強大的功能之一。 一旦您開始了解它的多功能性和所產生的代碼可讀性,您的Java代碼樣式將永遠改變。 與其使用for , if和switch語句以及眾多中間變量來充斥所有瑣碎的細節,您還可以使用Stream ,它僅包含要做什么的描述,而不是實際上是如何完成的。
幾年前,我們不得不為Java項目做出API決定:我們應該為兩種快速本地內存數據緩存方法選擇哪種返回類型;
- 唯一的搜索鍵,返回一個值或不返回任何值
- 一個非唯一的搜索鍵,它返回任意數量的值(零到無窮大)。
這是最初的想法:
Optional<T> searchUnique(K key); // For unique keys Stream<T> search(K key);? ? ? ? ?// For non-unique keys 但是,我們希望這兩個方法看起來完全相同,并且都返回一個
Stream<T> 。 然后,API看起來會更加整潔,因為唯一緩存將看上去與非唯一緩存完全相同。
但是,唯一搜索必須非常高效,并且每秒必須創建數百萬個結果對象,而又不會產生太多開銷。
解決方案
通過實現僅包含單個元素的SingletonStream (因此,與具有任意數量元素的普通Stream相比,可以進行高度優化),我們能夠讓這兩種方法在保持性能的同時返回Stream 。 如果未找到鍵,則方法searchUnique(K key)將返回一個空流( Stream.empty() ),如果該鍵存在,則它將返回SingletonStream以及與該鍵關聯的值。 我們會得到:
Stream<T> searchUnique(K key); // For unique keys Stream<T> search(K key); // For non-unique keys大! 我們可以吃餅干,仍然可以吃!
實施
SingletonStream是Speedment Stream ORM的一部分,可以在GitHub上查看。 隨意使用的Speedment自己的項目中使用Speedment任何它的組件的初始化 。
SingletonStream是使用JVM的Escape Analysis進行堆棧分配的不錯選擇(在我以前的文章中, 這里和此處有關Escape Analysis的更多信息 )。 該實現有兩種形式。 如果將STRICT值設置為true ,我們將獲得一個完全惰性的Stream ,但是缺點是,一旦調用諸如.filter(), map()等中間操作 ,我們將失去Singleton屬性 。另一方面,將STRICT值設置為false , SingletonStream會急切地執行許多中間操作 ,并且它將能夠返回新的SingletonStream從而保留Singleton屬性 。 在許多情況下,這將提供更好的性能。
這里為參考流設計的解決方案也可以很容易地修改為單例流的原始形式。 因此,編寫SingletonIntStream ,
SingletonLongStream和SingletonDoubleStream 。 這是SingletonLongStream 。
應該注意的是,該類可以進一步發展,以便它可以支持惰性評估,同時始終保持高性能。 這是未來的工作。
性能
有多種方法可以測試SingletonStream的性能,并將其與具有一個元素的標準Stream實現進行比較。
這是使用JMH的一種方法。 第一個測試(計數)僅對流中的元素數進行計數,第二個測試(forEach)對流中的一個元素執行某些操作。
@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筆記本電腦上運行時,將產生以下結果:
... 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 ...“計數”操作的加速因子超過10。 對于“ forEach”操作,看來JVM能夠完全優化SingletonStream的完整代碼路徑。
測試一下
使用Speedment 初始化程序下載Speedment。
完整的測試課程在這里可用。
結論
SingletonStream或多或少地作為擴展的Optional起作用,并在保持Stream庫優點的同時提供高性能。
您可以通過將STRICT值設置為首選的嚴格性/性能選擇來選擇它的兩個版本。
SingletonStream可以進一步改進。
翻譯自: https://www.javacodegeeks.com/2018/10/java-gain-performance-singletonstream.html
總結
以上是生活随笔為你收集整理的Java:使用SingletonStream获得性能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tomcat 正常关闭_Tomcat的带
- 下一篇: 9299 元,小米推出米家智能蒸烤一体集