使用Java流和In-JVM-Memory的超低延迟查询
自然界的基本規(guī)則(例如光速和通用信息論)對(duì)我們可以從傳統(tǒng)系統(tǒng)體系結(jié)構(gòu)中獲得的最大性能設(shè)置了明顯的限制。
了解您作為Java開發(fā)人員如何使用JVM技術(shù)和Java流將性能提高幾個(gè)數(shù)量級(jí)。
例如,如果應(yīng)用程序服務(wù)器和數(shù)據(jù)庫服務(wù)器相距100 m(約330英尺),則光速帶來的往返延遲將略微超過600 ns。 更重要的是,由于采用了TCP / IP協(xié)議,盡管采用了黑帶技巧(例如自定義內(nèi)核),但10 GBit / s連接上的單個(gè)數(shù)據(jù)包往返延遲幾乎無法優(yōu)化到小于25 us(= 25,000 ns)。構(gòu)建,繁忙的輪詢和CPU關(guān)聯(lián)性。
在本文中,我將展示如何使用JVM內(nèi)存技術(shù)直接從RAM創(chuàng)建Java Streams。 我們將使用名為Speedment的基于Stream的Java ORM,它可以使用標(biāo)準(zhǔn)格式執(zhí)行數(shù)據(jù)分析
java.util.stream.Stream對(duì)象以及如何在200 ns內(nèi)創(chuàng)建和完成其中一些流的方法,令人驚訝的是,這僅是訪問64位主內(nèi)存的CPU延遲的兩倍。
200 ns比遠(yuǎn)程數(shù)據(jù)庫(100 m)的理論最小延遲快125倍以上,該遠(yuǎn)程數(shù)據(jù)庫的內(nèi)部處理延遲為零,并且單個(gè)TCP數(shù)據(jù)包可以傳達(dá)查詢和響應(yīng)。 在實(shí)時(shí)方案中,數(shù)據(jù)庫的內(nèi)部處理延遲永遠(yuǎn)不會(huì)為零,并且查詢和結(jié)果通常都以多個(gè)TCP包發(fā)送。 因此,在許多情況下,加速因子可能是1000倍甚至更多。
數(shù)據(jù)庫
在下面的示例中,我們將Sakila數(shù)據(jù)庫內(nèi)容中的數(shù)據(jù)用于MySQL。 Sakila是為電影租賃商店建模的示例數(shù)據(jù)庫。 它具有名為Film,Actor,Category等的表格,可以在此處免費(fèi)下載。 應(yīng)該注意的是,這是一個(gè)小型數(shù)據(jù)庫,但事實(shí)證明,許多Speedment流操作的復(fù)雜度為O(1)或O(log(N()) ,因此無論大小如何,都確保相同的速度或較小的數(shù)據(jù)集。
步驟1:建立專案
首先,我們需要配置我們pom.xml -file使用最新Speedment依賴和Maven插件。 最快的方法是生成一個(gè)
使用可以在此處找到的Speedment Initializer的pom.xml -file。 首先,選擇數(shù)據(jù)庫類型“ MySQL”并確保啟用了“內(nèi)存中加速”,然后按“下載”,您將獲得一個(gè)完整的項(xiàng)目文件夾,其中包含為您自動(dòng)生成的Main.java文件。
接下來,解壓縮項(xiàng)目文件夾的zip文件,打開命令行,轉(zhuǎn)到解壓縮的文件夾( pom.xml文件所在的文件夾),然后輸入以下命令:
mvn speedment:tool接下來,連接到數(shù)據(jù)庫并開始:
步驟2:產(chǎn)生程式碼
從數(shù)據(jù)庫中加載模式數(shù)據(jù)后,可以通過按“生成”按鈕來生成完整的Java域模型。
步驟3:編寫應(yīng)用程序代碼
為了使用Speedment,首先需要?jiǎng)?chuàng)建一個(gè)Speedment實(shí)例。 這可以通過使用在步驟2中與域模型一起自動(dòng)生成的構(gòu)建器來完成。
Main.java文件并替換其中的代碼
此代碼段的main()方法:
為了演示基本功能,我們將首先編寫一個(gè)僅打印所有電影的應(yīng)用程序:
// 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);上面的代碼將產(chǎn)生以下輸出(為簡潔起見,以下簡稱):
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流支持所有流操作,包括過濾器。 假設(shè)我們只想過濾那些長于60分鐘的影片,并計(jì)算發(fā)生的次數(shù)。 可以這樣完成:
films.stream().filter(Film.LENGTH.greaterThan(60)).count();System.out.format("There are %,d films longer than 60 minutes.", count);這將產(chǎn)生以下輸出:
There are 896 films longer than 60 minutes 可以將任意數(shù)量的過濾器應(yīng)用于流,并將謂詞提供給
filter()方法可以使用
and() / or()運(yùn)算符。
步驟4:設(shè)定JMH
到目前為止,我們還沒有看到任何性能數(shù)據(jù)。 在本文中,我們將使用JMH進(jìn)行基準(zhǔn)測(cè)試。 JMH是用于構(gòu)建,運(yùn)行和分析以Java和其他針對(duì)JVM的其他語言編寫的基準(zhǔn)測(cè)試的Java工具。
我們將使用兩種流類型來進(jìn)行性能評(píng)估:
以下代碼摘錄顯示了我們將要運(yùn)行的基準(zhǔn)測(cè)試:
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(); }以下設(shè)置用于單線程延遲測(cè)量:
# 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數(shù)據(jù)庫進(jìn)行流傳輸
對(duì)我的筆記本電腦(MacBook Pro,2015年中,2.2 GHz Intel Core i7,16 GB RAM)上的標(biāo)準(zhǔn)MySQL數(shù)據(jù)庫(版本5.7.16)運(yùn)行這些查詢將產(chǎn)生以下輸出:
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數(shù)據(jù)庫中的JVM內(nèi)存加速功能進(jìn)行流傳輸
啟用JVM內(nèi)存中加速并在筆記本電腦上再次運(yùn)行相同的基準(zhǔn)測(cè)試,將產(chǎn)生以下結(jié)果:
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在一臺(tái)舊筆記本電腦上每秒能夠產(chǎn)生和消耗近1700萬個(gè)視頻流的能力真是令人驚訝。 具有許多CPU內(nèi)核的現(xiàn)代服務(wù)器級(jí)計(jì)算機(jī)將很容易每秒能夠產(chǎn)生和消耗超過2500萬個(gè)流。
延遲的JMH時(shí)間分辨率不足以測(cè)量足夠的準(zhǔn)確性。 通過使用一個(gè)線程運(yùn)行吞吐量測(cè)試并將結(jié)果取反,平均“過濾器和計(jì)數(shù)”延遲估計(jì)為1 / 5,564,678 = 180 ns。 這種更準(zhǔn)確的等待時(shí)間估算可提供大約5,000而非10,000的估算性能提升因子。
結(jié)論
啟用JVM中的內(nèi)存加速可以大大提高性能。 在上述基準(zhǔn)測(cè)試中:
單線程延遲減少了以下因素:
復(fù)合體:約3,000
篩選和計(jì)數(shù):?5,000
多線程吞吐量增加了以下因素:
綜合樓:2,700
篩選和計(jì)數(shù):5,300
作為說明,這意味著具有一百萬個(gè)子查詢的復(fù)合JVM操作會(huì)將其聚合數(shù)據(jù)延遲從1小時(shí)減少到1秒。
筆記
為了提高SQL性能,將流(自動(dòng))呈現(xiàn)給SQL查詢。 呈現(xiàn)的“過濾并計(jì)數(shù)” SQL查詢?nèi)缦滤?#xff1a;
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]評(píng)級(jí)列中定義了一個(gè)索引。
可以看出,所有計(jì)數(shù)都是在數(shù)據(jù)庫端完成的,并且流沒有將任何不必要的Film對(duì)象從數(shù)據(jù)庫拉入JMH應(yīng)用程序。
源代碼
可以在此處查看基準(zhǔn)測(cè)試的源代碼。
摘要
在本文中,您已經(jīng)了解了如何使用Speedment Free顯著減少數(shù)據(jù)分析Java應(yīng)用程序中的延遲,同時(shí)提高吞吐量。
加速因素是幾個(gè)數(shù)量級(jí)。
翻譯自: https://www.javacodegeeks.com/2018/09/ultra-low-latency-querying-with-java-streams-and-in-jvm-memory.html
總結(jié)
以上是生活随笔為你收集整理的使用Java流和In-JVM-Memory的超低延迟查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (业务管理系统ddos)
- 下一篇: 累积:轻松自定义Java收集器