使用Java流和In-JVM-Memory的超低延迟查询
自然界的基本規則(例如光速和通用信息論)對我們可以從傳統系統體系結構中獲得的最大性能設置了明顯的限制。
了解您作為Java開發人員如何使用JVM技術和Java流將性能提高幾個數量級。
例如,如果應用程序服務器和數據庫服務器相距100 m(約330英尺),則光速帶來的往返延遲將略微超過600 ns。 更重要的是,由于采用了TCP / IP協議,盡管采用了黑帶技巧(例如自定義內核),但10 GBit / s連接上的單個數據包往返延遲幾乎無法優化到小于25 us(= 25,000 ns)。構建,繁忙的輪詢和CPU關聯性。
在本文中,我將展示如何使用JVM內存技術直接從RAM創建Java Streams。 我們將使用名為Speedment的基于Stream的Java ORM,它可以使用標準格式執行數據分析
java.util.stream.Stream對象以及如何在200 ns內創建和完成其中一些流的方法,令人驚訝的是,這僅是訪問64位主內存的CPU延遲的兩倍。
200 ns比遠程數據庫(100 m)的理論最小延遲快125倍以上,該遠程數據庫的內部處理延遲為零,并且單個TCP數據包可以傳達查詢和響應。 在實時方案中,數據庫的內部處理延遲永遠不會為零,并且查詢和結果通常都以多個TCP包發送。 因此,在許多情況下,加速因子可能是1000倍甚至更多。
數據庫
在下面的示例中,我們將Sakila數據庫內容中的數據用于MySQL。 Sakila是為電影租賃商店建模的示例數據庫。 它具有名為Film,Actor,Category等的表格,可以在此處免費下載。 應該注意的是,這是一個小型數據庫,但事實證明,許多Speedment流操作的復雜度為O(1)或O(log(N()) ,因此無論大小如何,都確保相同的速度或較小的數據集。
步驟1:建立專案
首先,我們需要配置我們pom.xml -file使用最新Speedment依賴和Maven插件。 最快的方法是生成一個
使用可以在此處找到的Speedment Initializer的pom.xml -file。 首先,選擇數據庫類型“ MySQL”并確保啟用了“內存中加速”,然后按“下載”,您將獲得一個完整的項目文件夾,其中包含為您自動生成的Main.java文件。
接下來,解壓縮項目文件夾的zip文件,打開命令行,轉到解壓縮的文件夾( pom.xml文件所在的文件夾),然后輸入以下命令:
mvn speedment:tool接下來,連接到數據庫并開始:
步驟2:產生程式碼
從數據庫中加載模式數據后,可以通過按“生成”按鈕來生成完整的Java域模型。
步驟3:編寫應用程序代碼
為了使用Speedment,首先需要創建一個Speedment實例。 這可以通過使用在步驟2中與域模型一起自動生成的構建器來完成。
Main.java文件并替換其中的代碼
此代碼段的main()方法:
為了演示基本功能,我們將首先編寫一個僅打印所有電影的應用程序:
// Obtains a FilmManager that allows us to // work with the "film" table FilmManager films = app.getOrThrow(FilmManager.class);// Create a stream of films and print // each and every film films.stream().forEach(System.out::println);上面的代碼將產生以下輸出(為簡潔起見,以下簡稱):
FilmImpl { filmId = 1, title = ACADEMY DINOSAUR, …, length = 86, ... } FilmImpl { filmId = 2, title = ACE GOLDFINGER, ..., length = 48, ...} FilmImpl { filmId = 3, title = ADAPTATION HOLES, ..., length = 50, ...} ...步驟3:使用篩選器
Speedment流支持所有流操作,包括過濾器。 假設我們只想過濾那些長于60分鐘的影片,并計算發生的次數。 可以這樣完成:
films.stream().filter(Film.LENGTH.greaterThan(60)).count();System.out.format("There are %,d films longer than 60 minutes.", count);這將產生以下輸出:
There are 896 films longer than 60 minutes 可以將任意數量的過濾器應用于流,并將謂詞提供給
filter()方法可以使用
and() / or()運算符。
步驟4:設定JMH
到目前為止,我們還沒有看到任何性能數據。 在本文中,我們將使用JMH進行基準測試。 JMH是用于構建,運行和分析以Java和其他針對JVM的其他語言編寫的基準測試的Java工具。
我們將使用兩種流類型來進行性能評估:
以下代碼摘錄顯示了我們將要運行的基準測試:
private static final Predicate RATING_EQUALS_PG_13 = Film.RATING.equal(Rating.PG13);private static final Comparator LENGTH_DESCENDING =Film.LENGTH.reversed();@Benchmark public long filterAndCount() {return films.stream().filter(RATING_EQUALS_PG_13).count(); }@Benchmark public IntSummaryStatistics complex() {return films.stream().sorted(LENGTH_DESCENDING).skip(745).limit(5).mapToInt(Film.RENTAL_DURATION.asInt()).summaryStatistics(); }以下設置用于單線程延遲測量:
# JMH version: 1.21 # VM version: JDK 10, Java HotSpot(TM) 64-Bit Server VM, 10+46 # VM invoker: /Library/Java/JavaVirtualMachines/jdk-10.jdk/Contents/Home/bin/java # VM options: -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=63173:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 # Warmup: 5 iterations, 10 s each # Measurement: 5 iterations, 10 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Average time, time/op # Benchmark: com.example.Bench.complex使用SQL與MySQL數據庫進行流傳輸
對我的筆記本電腦(MacBook Pro,2015年中,2.2 GHz Intel Core i7,16 GB RAM)上的標準MySQL數據庫(版本5.7.16)運行這些查詢將產生以下輸出:
SINGLE-THREADED LATENCY (Lower is better) Benchmark Mode Cnt Score Error Units Bench.complex avgt 5 0.003 ± 0.001 s/op Bench.filterAndCount avgt 5 0.001 ± 0.001 s/opMULTI-THREADED THROUGHPUT (Higher is better) Benchmark Mode Cnt Score Error Units Bench.complex thrpt 5 1714.980 ± 343.655 ops/s Bench.filterAndCount thrpt 5 3154.984 ± 318.881 ops/s使用MySQL數據庫中的JVM內存加速功能進行流傳輸
啟用JVM內存中加速并在筆記本電腦上再次運行相同的基準測試,將產生以下結果:
SINGLE-THREADED LATENCY (Lower is better) Benchmark Mode Cnt Score Error Units Bench.complex avgt 5 ≈ 10?? s/op Bench.filterAndCount avgt 5 ≈ 10?? s/opMULTI-THREADED THROUGHPUT (Higher is better) Benchmark Mode Cnt Score Error Units Bench.complex thrpt 5 4793915.881 ± 374680.158 ops/s Bench.filterAndCount thrpt 5 16958800.191 ± 1023015.568 ops/s在一臺舊筆記本電腦上每秒能夠產生和消耗近1700萬個視頻流的能力真是令人驚訝。 具有許多CPU內核的現代服務器級計算機將很容易每秒能夠產生和消耗超過2500萬個流。
延遲的JMH時間分辨率不足以測量足夠的準確性。 通過使用一個線程運行吞吐量測試并將結果取反,平均“過濾器和計數”延遲估計為1 / 5,564,678 = 180 ns。 這種更準確的等待時間估算可提供大約5,000而非10,000的估算性能提升因子。
結論
啟用JVM中的內存加速可以大大提高性能。 在上述基準測試中:
單線程延遲減少了以下因素:
復合體:約3,000
篩選和計數:?5,000
多線程吞吐量增加了以下因素:
綜合樓:2,700
篩選和計數:5,300
作為說明,這意味著具有一百萬個子查詢的復合JVM操作會將其聚合數據延遲從1小時減少到1秒。
筆記
為了提高SQL性能,將流(自動)呈現給SQL查詢。 呈現的“過濾并計數” SQL查詢如下所示:
SELECT COUNT(*) FROM (SELECT `film_id`,`title`,`description`,`release_year`, `language_id`,`original_language_id`,`rental_duration`,`rental_rate`, `length`,`replacement_cost`,`rating`,`special_features`,`last_update` FROM`sakila`.`film` WHERE (`rating` = ? COLLATE utf8_bin) ) AS A , values:[PG-13]評級列中定義了一個索引。
可以看出,所有計數都是在數據庫端完成的,并且流沒有將任何不必要的Film對象從數據庫拉入JMH應用程序。
源代碼
可以在此處查看基準測試的源代碼。
摘要
在本文中,您已經了解了如何使用Speedment Free顯著減少數據分析Java應用程序中的延遲,同時提高吞吐量。
加速因素是幾個數量級。
翻譯自: https://www.javacodegeeks.com/2018/09/ultra-low-latency-querying-with-java-streams-and-in-jvm-memory.html
總結
以上是生活随笔為你收集整理的使用Java流和In-JVM-Memory的超低延迟查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (业务管理系统ddos)
- 下一篇: 云平台备案是什么(云平台备案)