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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

koa中上传文件到阿里云oss实现点击在线预览和下载

比较好的在线预览的方法&#xff1a; 跳转一个新的页面&#xff0c;里面放一个iframe标签&#xff0c;或者object标签 <iframe src"xxx"></iframe> <object data"xxx"></object> 但是这两个标签也有限制&#xff0c;有些可以直接…

反序列化 还是记一下吧

JsonConvert.DeserializeObject<dynamic>(result) https://www.cnblogs.com/caofangsheng/p/5687994.html 转载于:https://www.cnblogs.com/sajiao/p/10303072.html

三菱st语言编程实例_LD、FBD、IL、ST、SFC、CFC六种编程语言的特点

CODESYS共支持六中不同的编程语言&#xff0c;很多学者在学习的过程中常会问一个问题&#xff0c;哪种编程语言最好&#xff1f;其实本人觉得没有哪种编程语言是绝对的好或不好&#xff0c;不同的工程应用具有不同的最佳编程方式&#xff0c;每种编程语言都具有其不同的特点&am…

假定某一个数据列表是一个班级的计算机课程,若需要利用形参直接访问实参,则应把形参变量说明为()参数。A.指针B.引用C.传值D.常值...

参考答案如下有机化合物系统命名法中&#xff0c;若需根据位次规则给官能团和取代基定位&#xff0c;常用 ( ) 编号要利用形引用RGB是与设备无关的色彩空间。参直参参变参数传值常值病毒灭活是指在理化因素作用下使病毒失去A1在后场向前场传球时&#xff0c;接访球触碰到了双脚…

爬虫

爬虫 1、设计 分布式爬虫系统允许位于多个不同主机上的爬虫程序并行爬取提交的爬虫作业&#xff0c;进而协调他们之间的爬取能力。爬取队列由redis管理&#xff0c;每个spider通过修改的调度程序从queue中拉取job。 页面被spider成功爬取后&#xff0c;就交给管线进行进一步处理…

python下划线怎么输入_python下划线怎么打出来

python中下划线使用键盘上的Shift减号键即可打出&#xff0c;减号键位于0和加号键之间。 在Python中下划线还具有 private 和 protected 类似的访问权限作用&#xff0c;下面我们具体分析。Python主要存在四种命名&#xff1a; &#xff08;1&#xff09;object #公用方法 &…

在测试中使用匹配器

我们被迫在测试代码中写太多断言行的日子已经一去不复返了。 镇上有一个新的警长&#xff1a;assertThat和他的代理人&#xff1a;匹配者。 好吧&#xff0c;这不是什么新东西&#xff0c;但是无论如何&#xff0c;我想向您介绍匹配器的使用方式&#xff0c;然后对匹配器概念进…

二、先在SD卡上启动U-boot,再烧写新的U-boot进Nandflash

1. 制作SD卡 先准备一张2G的SD卡&#xff08;不能用8G的&#xff0c;2G的卡和8G的卡协议不一样&#xff09;&#xff0c;和烧写SD卡的工具write_sd以及需要烧写到SD卡中的u-boot-movi.bin。将SD卡格式化后连接到Ubuntu虚拟机中&#xff0c;注意在SD卡需要插入到读卡器中&#x…

泉州经贸职业技术学院计算机系,部门简介-泉州经贸职业技术学院网络电教中心...

泉州经贸职业技术学院网络电教中心成立于2004年&#xff0c;是学院教学辅助部门&#xff0c;为学院教学、行政和后勤等工作提供计算机及网络技术支持。网络电教中心是学院信息化建设职能部门&#xff0c;主要负责各类计算机公共机房、多媒体教室的运行与维护&#xff0c;学院信…

编译型语言,解释型语言,脚本语言

编译型语言 编译型语言在执行之前就将代码编译成了机器语言&#xff0c;当执行的时候就直接运行机器语言&#xff0c;就可以了&#xff0c;如java&#xff0c;编译之后产生.class文件&#xff0c;然后JVM直接执行编译产生的文件就可以了&#xff0c;只要源代码没有发生改变&…

pandas 生成html表格_Pandas 读写html

Pandas 读写html,pandas提供read_html(),to_html()两个函数用于读写html格式的文件。这两个函数非常有用,把DataFrame等复杂的数据结构转换成HTML表格很简单,无需编写一长串HTML代码就能实现。pandas这方面的能力很强大,如果你从事web开发,这个功能将给你带来很多便捷。 读…

java comparator_Java基础之String漫谈(二)

Java-String1. 导读上期分享了本人关于String四个问题, 本期我们继续探讨String中的两个问题:.1 String既然已经实现了Comparable接口, 为什么还要提供内部类----CaseInsensitiveComparator;.2 使用 "" 拼接String究竟干了什么? 为什么在循环中不让使用""…

vue给input file绑定函数获取当前上传的对象

HTML<input type"file" change"tirggerFile($event)"> JS(vue-methods)tirggerFile : function (event) {var file event.target.files; // (利用console.log输出看结构就知道如何处理档案资料)// do something... } 如果直接在绑定的函数中传入thi…

掌握Java字节码

嘿! Happy Advent&#xff1a;D我是ZeroTurnaround的技术布道者Simon Maple&#xff08; sjmaple&#xff09; 。 您知道&#xff0c; JRebel伙计们&#xff01; 由于编写了类似于JRebel的产品&#xff0c;该产品与字节码进行交互的结果比您想像的更多&#xff0c;因此&#xf…

elasticsearch——海量文档高性能索引系统

elasticsearch elasticsearch是一个高性能高扩展性的索引系统&#xff0c;底层基于apache lucene。 可结合kibana工具进行可视化。 概念&#xff1a; index 索引: 类似SQL中的一张表&#xff0c;索引名必须是全小写单词。type&#xff08;索引类型&#xff09;&#xff1a;设计…

全国计算机c二级编程题,全国计算机二级C上机 编程题.doc

全国计算机二级C上机 编程题.doc全国计算机二级C上机 编程题全国计算机等级考试C语言――编程题1&#xff0e;m个人的成绩存放在score数组中,请编写函数fun,它的功能是:将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指的数组中。例如,当score数组中的数据为…

.Net架构篇:思考如何设计一款实用的分布式监控系统?

前言无论从最早期的unix操作系统&#xff0c;还是曾经大行其道的单体式应用&#xff0c;还是现在日益流行的微服务架构&#xff0c;始终都离不开监控的身影。如windows的任务管理器&#xff0c;linux的top命令&#xff0c;都可以看作是监控的面板。再联系起现实生活&#xff0c…

敲代码括号技巧_理解代码块概念,养成良好编程习惯 | 亲子课堂 第 3 课

亲子课堂关卡解析 / 英语教学 / 编程讲解 做亲子编程教育的好帮手&#xff01; 每周二、四定期更新 地牢面向真正0编程基础的孩子们&#xff0c;关卡被设计成迷宫的形式&#xff0c;引导孩子们使用编程思维解决问题。以循序渐进的方式&#xff0c;让大家理解掌握几个Pyth…

在struts2中push方法的使用_电脑使用中怎么截屏的几种方法

电脑在日常工作中经常需要用到截屏的操作&#xff0c;为了截取画面提供证明或者说明&#xff0c;像我就经常需要用到&#xff0c;当然我在写文章的时候更是需要用到&#xff0c;来配合文字的描述&#xff0c;使大家能更直观更容易的去操作&#xff0c;以达到快速解决电脑问题的…

vue父组件向子组件动态传值的两种方法

在一些项目需求中需要父组件向子组件动态传值&#xff0c;比如我这里的需求是&#xff0c;父组件动态通过axios获取返回的图片url数组然后传给子组件&#xff0c;上传图片的子组件拿到该数组后进行遍历并展示图片&#xff0c;因为有时候获取到的会是空&#xff0c;所以这里要考…