<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ![](https://cdn.zimug.com/wx-zimug.png) 下面是視頻(優酷的清晰度有限):還是建議大家去B站觀看:[B站觀看地址](https://www.bilibili.com/video/BV1sE411P7C1/)。如果您覺得我做的工作對您有幫助,請去B站點贊、關注、轉發、收藏,您的支持是我不竭的創作動力! ```[youku] XNDYxMzYyODYzMg ``` ## 一、粉絲的反饋 ![](https://img.kancloud.cn/88/15/8815b15ca9b6236b3f92dea23eac2cc2_1076x263.png) **問:stream比for循環慢5倍,用這個是為了啥?** 答:互聯網是一個新聞泛濫的時代,三人成虎,以假亂真的事情時候發生。作為一個技術開發者,要自己去動手去做,不要人云亦云。 的確,這位粉絲說的這篇文章我也看過,我就不貼地址了,也沒必要給他帶流量。怎么說呢?就是一個不懂得測試的、不入流開發工程師做的性能測試,給出了一個危言聳聽的結論。 ## 二、所有性能測試結論都是片面的 性能測試是必要的,但針對性能測試的結果,永遠要持懷疑態度。為什么這么說? * 性能測試脫離業務場景就是片面的性能測試。你能覆蓋所有的業務場景么? * 性能測試脫離硬件環境就是片面的性能測試。你能覆蓋所有的硬件環境么? * 性能測試脫離開發人員的知識面就是片面的性能測試。你能覆蓋各種開發人員奇奇怪怪的代碼么? 所以,我從來不相信網上的任何性能測試的文章。凡是我自己的從事的業務場景,我都要在接近生產環境的機器上自己測試一遍。 **所有性能測試結論都是片面的,只有你生產環境下的運行結果才是真的。** ## 三、動手測試Stream的性能 ### 3.1.環境 windows10 、16G內存、i7-7700HQ 2.8HZ 、64位操作系統、JDK 1.8.0_171 ### 3.2.測試用例與測試結論 我們在上一節,已經講過: * 針對不同的數據結構,Stream流的執行效率是不一樣的 * 針對不同的數據源,Stream流的執行效率也是不一樣的 所以記住筆者的話:**所有性能測試結論都是片面的**,你要自己動手做,相信你自己的代碼和你的環境下的測試!我的測試結果僅僅代表我自己的測試用例和測試數據結構! #### 3.2.1.測試用例一 測試用例:5億個int隨機數,求最小值 測試結論(測試代碼見后文): * 使用普通for循環,執行效率是Stream串行流的2倍。也就是說普通for循環性能更好。 * Stream并行流計算是普通for循環執行效率的4-5倍。 * Stream并行流計算 > 普通for循環 > Stream串行流計算 ![](https://img.kancloud.cn/dd/60/dd60020d6d0e0a6f0c21d40cac3fbc38_658x1710.png) ### 3.2.測試用例二 測試用例:長度為10的1000000隨機字符串,求最小值 測試結論(測試代碼見后文): * 普通for循環執行效率與Stream串行流不相上下 * Stream并行流的執行效率遠高于普通for循環 * Stream并行流計算 > 普通for循環 = Stream串行流計算 ![](https://img.kancloud.cn/9a/25/9a255a77b70ff19563f706b14d5afb5d_652x1728.png) ### 3.3.測試用例三 測試用例:10個用戶,每人200個訂單。按用戶統計訂單的總價。 測試結論(測試代碼見后文): * Stream并行流的執行效率遠高于普通for循環 * Stream串行流的執行效率大于等于普通for循環 * Stream并行流計算 > Stream串行流計算 >= 普通for循環 ![](https://img.kancloud.cn/ea/d5/ead5d37c2fa78177ab100c20ce41c36f_655x1764.png) ## 四、最終測試結論 * 對于簡單的數字(list-Int)遍歷,普通for循環效率的確比Stream串行流執行效率高(1.5-2.5倍)。但是Stream流可以利用并行執行的方式發揮CPU的多核優勢,因此并行流計算執行效率高于for循環。 * 對于list-Object類型的數據遍歷,普通for循環和Stream串行流比也沒有任何優勢可言,更不用提Stream并行流計算。 雖然在不同的場景、不同的數據結構、不同的硬件環境下。Stream流與for循環性能測試結果差異較大,甚至發生逆轉。**但是總體上而言**: * Stream并行流計算 >> 普通for循環 ~= Stream串行流計算 (之所以用兩個大于號,你細品) * 數據容量越大,Stream流的執行效率越高。 * Stream并行流計算通常能夠比較好的利用CPU的多核優勢。CPU核心越多,Stream并行流計算效率越高。 stream比for循環慢5倍?也許吧,單核CPU、串行Stream的int類型數據遍歷?我沒試過這種場景,但是我知道這不是應用系統的核心場景。看了十幾篇測試博文,和我的測試結果。我的結論是: **在大多數的核心業務場景下及常用數據結構下,Stream的執行效率比for循環更高。** 畢竟我們的業務中通常是實實在在的實體對象,沒事誰總對`List<Int>`類型進行遍歷?誰的生產服務器是單核?。 ## 五、測試代碼 ~~~ <dependency> <groupId>com.github.houbb</groupId> <artifactId>junitperf</artifactId> <version>2.0.0</version> </dependency> ~~~ 測試用例一: ~~~ import com.github.houbb.junitperf.core.annotation.JunitPerfConfig; import com.github.houbb.junitperf.core.report.impl.HtmlReporter; import org.junit.jupiter.api.BeforeAll; import java.util.Arrays; import java.util.Random; public class StreamIntTest { public static int[] arr; @BeforeAll public static void init() { arr = new int[500000000]; //5億個隨機Int randomInt(arr); } @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class}) public void testIntFor() { minIntFor(arr); } @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class}) public void testIntParallelStream() { minIntParallelStream(arr); } @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class}) public void testIntStream() { minIntStream(arr); } private int minIntStream(int[] arr) { return Arrays.stream(arr).min().getAsInt(); } private int minIntParallelStream(int[] arr) { return Arrays.stream(arr).parallel().min().getAsInt(); } private int minIntFor(int[] arr) { int min = Integer.MAX_VALUE; for (int anArr : arr) { if (anArr < min) { min = anArr; } } return min; } private static void randomInt(int[] arr) { Random r = new Random(); for (int i = 0; i < arr.length; i++) { arr[i] = r.nextInt(); } } } ~~~ 測試用例二: ~~~ import com.github.houbb.junitperf.core.annotation.JunitPerfConfig; import com.github.houbb.junitperf.core.report.impl.HtmlReporter; import org.junit.jupiter.api.BeforeAll; import java.util.ArrayList; import java.util.Random; public class StreamStringTest { public static ArrayList<String> list; @BeforeAll public static void init() { list = randomStringList(1000000); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testMinStringForLoop(){ String minStr = null; boolean first = true; for(String str : list){ if(first){ first = false; minStr = str; } if(minStr.compareTo(str)>0){ minStr = str; } } } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void textMinStringStream(){ list.stream().min(String::compareTo).get(); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testMinStringParallelStream(){ list.stream().parallel().min(String::compareTo).get(); } private static ArrayList<String> randomStringList(int listLength){ ArrayList<String> list = new ArrayList<>(listLength); Random rand = new Random(); int strLength = 10; StringBuilder buf = new StringBuilder(strLength); for(int i=0; i<listLength; i++){ buf.delete(0, buf.length()); for(int j=0; j<strLength; j++){ buf.append((char)('a'+ rand.nextInt(26))); } list.add(buf.toString()); } return list; } } ~~~ 測試用例三: ~~~ import com.github.houbb.junitperf.core.annotation.JunitPerfConfig; import com.github.houbb.junitperf.core.report.impl.HtmlReporter; import org.junit.jupiter.api.BeforeAll; import java.util.*; import java.util.stream.Collectors; public class StreamObjectTest { public static List<Order> orders; @BeforeAll public static void init() { orders = Order.genOrders(10); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testSumOrderForLoop(){ Map<String, Double> map = new HashMap<>(); for(Order od : orders){ String userName = od.getUserName(); Double v; if((v=map.get(userName)) != null){ map.put(userName, v+od.getPrice()); }else{ map.put(userName, od.getPrice()); } } } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testSumOrderStream(){ orders.stream().collect( Collectors.groupingBy(Order::getUserName, Collectors.summingDouble(Order::getPrice))); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testSumOrderParallelStream(){ orders.parallelStream().collect( Collectors.groupingBy(Order::getUserName, Collectors.summingDouble(Order::getPrice))); } } class Order{ private String userName; private double price; private long timestamp; public Order(String userName, double price, long timestamp) { this.userName = userName; this.price = price; this.timestamp = timestamp; } public String getUserName() { return userName; } public double getPrice() { return price; } public long getTimestamp() { return timestamp; } public static List<Order> genOrders(int listLength){ ArrayList<Order> list = new ArrayList<>(listLength); Random rand = new Random(); int users = listLength/200;// 200 orders per user users = users==0 ? listLength : users; ArrayList<String> userNames = new ArrayList<>(users); for(int i=0; i<users; i++){ userNames.add(UUID.randomUUID().toString()); } for(int i=0; i<listLength; i++){ double price = rand.nextInt(1000); String userName = userNames.get(rand.nextInt(users)); list.add(new Order(userName, price, System.nanoTime())); } return list; } @Override public String toString(){ return userName + "::" + price; } } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看