日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ArrayList与LinkedList

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ArrayList与LinkedList 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我必須承認這篇文章的標題有點吸引人。 我最近閱讀了此博客文章 ,這是有關此主題的討論和辯論的一個很好的摘要。

但是這次,我想嘗試一種不同的方法來比較這兩個眾所周知的數據結構:使用硬件性能計數器 。

我不會進行微基準測試,也不能直接進行。 我不會使用System.nanoTime()計時,而是使用HPC(例如高速緩存命中/未命中)。

無需介紹這些數據結構,每個人都知道它們的用途以及實現方式。 我將研究重點放在列表迭代上,因為除了添加元素之外,這是列表最常見的任務。 同時也因為列表的內存訪問模式是CPU緩存交互的一個很好的例子。

這是我的用于測量LinkedList和ArrayList的列表迭代的代碼:

import java.util.ArrayList; import java.util.LinkedList; import java.util.List;import ch.usi.overseer.OverHpc;public class ListIteration {private static List<String> arrayList = new ArrayList<>();private static List<String> linkedList = new LinkedList<>();public static void initializeList(List<String> list, int bufferSize){for (int i = 0; i < 50000; i++){byte[] buffer = null;if (bufferSize > 0){buffer = new byte[bufferSize];}String s = String.valueOf(i);list.add(s);// avoid buffer to be optimized awayif (System.currentTimeMillis() == 0){System.out.println(buffer);}}}public static void bench(List<String> list){if (list.contains("bar")){System.out.println("bar found");}}public static void main(String[] args) throws Exception{if (args.length != 2) return;List<String> benchList = "array".equals(args[0]) ? arrayList : linkedList;int bufferSize = Integer.parseInt(args[1]);initializeList(benchList, bufferSize);HWCounters.init();System.out.println("init done");// warmupfor (int i = 0; i < 10000; i++){bench(benchList);}Thread.sleep(1000);System.out.println("warmup done");HWCounters.start();for (int i = 0; i < 1000; i++){bench(benchList);}HWCounters.stop();HWCounters.printResults();HWCounters.shutdown();} }

為了進行測量,我使用基于監督程序庫的名為HWCounters的類來獲取硬件性能計數器。 您可以在這里找到此類的代碼。

該程序采用2個參數:第一個參數用于ArrayList實現或LinkedList之間的選擇,第二個參數用于initializeList方法中使用的緩沖區大小。 此方法使用50K字符串填充列表實現。 每個字符串都是剛創建的,即將添加到列表中。 我們也可以根據程序的第二個參數分配一個緩沖區。 如果為0,則不分配緩沖區。
bench方法執行對列表中未包含的常量字符串的搜索,因此我們完全遍歷了列表。

最后, main方法是執行列表的初始化,對基準方法進行預熱并測量該方法的1000次運行。 然后,我們從HPC打印結果。

讓我們在不帶2 Xeon X5680的Linux上不分配緩沖區的情況下運行程序:

[root@archi-srv]# java -cp .:overseer.jar com.ullink.perf.myths.ListIteration?array 0 init done warmup done Cycles: 428,711,720 Instructions: 776,215,597 L2 hits: 5,302,792 L2 misses: 23,702,079 LLC hits: 42,933,789 LLC misses: 73 CPU migrations: 0 Local DRAM: 0 Remote DRAM: 0[root@archi-srv]# /java -cp .:overseer.jar com.ullink.perf.myths.ListIteration?linked 0 init done warmup done Cycles: 767,019,336 Instructions: 874,081,196 L2 hits: 61,489,499 L2 misses: 2,499,227 LLC hits: 3,788,468 LLC misses: 0 CPU migrations: 0 Local DRAM: 0 Remote DRAM: 0

第一次運行是在ArrayList實現上,第二次是使用LinkedList。

  • 周期數是執行代碼所花費的CPU周期數。 顯然,LinkedList比ArrayList花費了更多的周期。
  • LinkedList的說明要高一些。 但這在這里并不重要。
  • 對于L2緩存訪問,我們有一個明顯的區別:與LinkedList相比,ArrayList的L2未命中率要高得多。
  • 從機械上講,LLC命中對ArrayList非常重要。

進行此比較的結論是,列表迭代期間訪問的大多數數據位于LinkedList的L2中,但位于ArrayList的L3中。

我對此的解釋是,添加到列表中的字符串是在之前創建的。 對于LinkedList,這意味著它是本地的在添加元素時創建的Node條目。 我們在節點上有更多位置。

但是,讓我們使用為每個新添加的String分配的中間緩沖區重新運行比較。

[root@archi-srv]# java -cp .:overseer.jar com.ullink.perf.myths.ListIteration array 256 init done warmup done Cycles: 584,965,201 Instructions: 774,373,285 L2 hits: 952,193 L2 misses: 62,840,804 LLC hits: 63,126,049 LLC misses: 4,416 CPU migrations: 0 Local DRAM: 824 Remote DRAM: 0[root@archi-srv]# java -cp .:overseer.jar com.ullink.perf.myths.ListIteration linked 256 init done warmup done Cycles: 5,289,317,879 Instructions: 874,350,022 L2 hits: 1,487,037 L2 misses: 75,500,984 LLC hits: 81,881,688 LLC misses: 5,826,435 CPU migrations: 0 Local DRAM: 1,645,436 Remote DRAM: 1,042

這里的結果有很大的不同:

  • 循環的重要性提高了10倍。
  • 說明與以前相同
  • 對于緩存訪問,ArrayList具有比先前運行更多的L2未命中/ LLC命中,但仍處于相同的數量級順序。 相反,LinkedList具有更多的L2未命中/ LLC命中,但此外,還有相當數量的LLC未命中/ DRAM訪問。 區別就在這里。

使用中間緩沖區,我們可以推開條目和字符串,這會產生更多的高速緩存未命中,并且最終還會訪問DRAM,這比訪問高速緩存要慢得多。

ArrayList在這里更可預測,因為我們彼此之間保持元素的局部性。

此處的內存訪問模式對于列表迭代性能至關重要。 ArrayList比LinkedList更穩定,因為在每個元素添加之間進行任何操作,都可以使數據保持比LinkedList更本地。

還要記住,對數組進行迭代對于CPU而言效率要高得多,因為它可以觸發硬件預取,因為訪問模式是非常可預測的。

Java出現日歷博客上的JCG合作伙伴 Jean-Philippe BEMPEL的參考: ArrayList與LinkedList 。

翻譯自: https://www.javacodegeeks.com/2013/12/arraylist-vs-linkedlist.html

總結

以上是生活随笔為你收集整理的ArrayList与LinkedList的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。