文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

访问数组的任意位置元素的性能真的一样?

2024-12-03 16:33

关注

 在我们的观念当中,数组成员访问的时间复杂度是O(1),每个成员都可以一次定位,因此访问时间应该是一样的。

那如果我说,现在有一个一千万元素的数组,那么访问第一个元素与访问最后一样元素的时间是一样的吗?这个时候你会不会有所犹豫呢?

实际动手验证

实践是检验真理的唯一手段。空想没用,我们动手实际测试一下。我们实现如下所示的代码,在该代码中我们创建一个全局的数组,数组的大小是一千万个元素。然后分别对第一个元素和最后一个元素赋值,并在赋值前后记录时间。

  1. #define BUF_SIZE 10000000 //一千万个元素 
  2.  
  3. int test_array[BUF_SIZE] = {}; 
  4.  
  5. int main( int argc, char* argv[] ) 
  6.  
  7.  
  8. long time1; 
  9.  
  10. long time2; 
  11.  
  12. time1 = get_time(); //获取时间,单位是纳秒 
  13.  
  14. test_array[0] = 1; //访问第一个元素 
  15.  
  16. time2 = get_time(); 
  17.  
  18. printf("access first item time: %ld\n", time2-time1); 
  19.  
  20. time1 = get_time(); 
  21.  
  22. test_array[BUF_SIZE-1] = 1; //访问最后一个元素 
  23.  
  24. time2 = get_time(); 
  25.  
  26. printf("access last item time: %ld\n", time2- time1); 
  27.  
  28. return(0); 
  29.  

 完成代码后,我们编译运行一下。为了得到稳定可靠的结果,我们多运行几次。得到的结果如下所示。


从测试结果可以看出,访问最后一个元素的性能明显要比访问第一个元素慢得多,有几十倍的性能差异!

原因分析

要想搞清楚上述问题的原因,需要更加深入的理解计算机的原理,包括可执行程序的内存布局、操作系统进程的原理以及硬件层面的一些知识。接下来我们将逐步介绍相关内容,抽丝剥茧,搞清楚为什么有如此明显的性能差异。

我们知道用户态的程序都是运行在虚拟空间的,每个程序都有自己4GB的虚拟空间。这个虚拟空间又称为虚拟内存。程序的虚拟内存并不是即刻分配的,而是按需分配。也就是说,只有在用户访问该部分内存的数据的时候,操作系统才会分配对应的物理内存,然后将数据加载到内存中。显然,这种从硬盘再读取数据的速度肯定要比直接访问内存慢的多。

 

现代的CPU为了提高系统采用了多级缓存和流水线技术。CPU会根据程序的指令运行情况将部分数据或者指令预加载到缓存当中,这样接下来就可以直接从从缓存读取数据了。

 

根据存储性能金字塔的数据,从缓存读取数据的性能是从内存读取性能的10倍以上。因此,如果代码没有规律,CPU无法预取数据和指令,那么程序的运行效率肯定会很低。

扯了这么远,让我们回到题目本身。由于这里数组比较大,因此当访问第一个元素的时候,第一千万个元素肯定是没有被预读的,之后访问该数据大概率会发生缺页中断。所以,访问第一个元素和最后一个元素在性能上是有差异的。

进一步的验证

有了上面的分析,我们可以再做进一步的验证。比如我们可以连续两次访问最后一个元素,看看两者的区别。

  1. int main( int argc, char* argv[] ) 
  2.  
  3.  
  4. long time1; 
  5.  
  6. long time2; 
  7.  
  8. time1 = get_time(); 
  9.  
  10. test_array[0] = 1; 
  11.  
  12. time2 = get_time(); 
  13.  
  14. printf("access first item time: %ld\n", time2-time1); 
  15.  
  16. time1 = get_time(); 
  17.  
  18. test_array[BUF_SIZE-1] = 1; // 第一次访问最后一个元素 
  19.  
  20. time2 = get_time(); 
  21.  
  22. printf("access last item time: %ld\n", time2- time1); 
  23.  
  24. time1 = get_time(); 
  25.  
  26. test_array[BUF_SIZE-1] = 1; // 第二次访问最后一个元素 
  27.  
  28. time2 = get_time(); 
  29.  
  30. printf("access last item time: %ld\n", time2- time1); 
  31.  
  32. return(0); 
  33.  

 修改完代码之后,执行该程序。同样,我们多次执行该程序,确保结果稳定。通过下面执行结果可以看到,在第二次执行是其时间与访问第一个元素相当,已经没有那么明显的差异了。


通过上面的学习,大家是不是觉得深入学习计算机原理层面的重要性了。关于更多计算机深层次的内容,我们后面会继续分享给大家。

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯