【突发奇想 之 vector使用时性能测试】

news/2024/11/16 4:45:54/

目录:

  • 前言
  • 分析vector不同操作对时间的影响
    • 1.for循环中使用 size()成员函数
    • 2.初始化时初始化为0,与其他值
    • 3.vector分配容量问题
    • 4. vector赋值操作
    • 5. 遍历:下标和迭代器
  • 总结

前言

打怪升级:第90天
在这里插入图片描述

分析vector不同操作对时间的影响

1.for循环中使用 size()成员函数

#include<iostream>
#include<ctime> // time_t, clock
#include<vector>using namespace std;#define NUM 1000000void test_time_1()
{vector<int>v1(NUM);for (int i = 0; i < NUM; ++i) v1[i] = i;int k = 0;time_t begin1 = clock();for (int i = 0; i < v1.size(); ++i){for (int j = 0; j < v1.size(); ++j){++k;}}time_t end1 = clock();k = 0;time_t begin2 = clock();size_t size = v1.size();for (int i = 0; i < size; ++i){for (int j = 0; j < size; ++j){++k;}}time_t end2 = clock();cout << "v1.size(), time: " << end1 - begin1 << endl;cout << "size,      time: " << end2 - begin2 << endl;
}

在这里插入图片描述

  • 结果
    debug下使用变量快很多很多(20倍左右),release下两者差别不大。

  • 结论
    在release模式下可能编译器对函数调用做了很大优化;
    但是循环中,还是推荐使用变量保存size,否则每次循环都需要调用 size()成员函数,量级大的情况下消耗还是不小的。


2.初始化时初始化为0,与其他值


#define NUM 100000000 void test_time_2()
{time_t begin1 = clock();// vector<int>v1(NUM);vector<vector<int> >v1(NUM, vector<int>(NUM));time_t end1 = clock();time_t begin2 = clock();//vector<int>v2(NUM, 0);vector<vector<int> >v2(NUM, vector<int>(NUM, 0));time_t end2 = clock();time_t begin3 = clock();// vector<int>v3(NUM, -1);vector<vector<int> >v3(NUM, vector<int>(NUM, 1));time_t end3 = clock();cout << "init empty, time: " << end1 - begin1 << endl;cout << "init zero,  time: " << end2 - begin2 << endl;cout << "init 100,   time: " << end3 - begin3 << endl;
}

这里是引用
在这里插入图片描述

  • 结果
    a. 一维数组:不初始化或者初始化为0都比较快
    如果初始化为其他值:1也好,3423121也好,时间消耗都会增大很多(20倍左右),同时,不同初始化值所用时间是一样的
    b. 二维数组:三者时间差别不大。

  • 结论
    如果后续需要输入其他数据,不初始化即可;
    如果不是必要不建议刚开始就全部初始化为非0值


3.vector分配容量问题


#define NUM 100000000 void test_time_3()
{time_t begin1 = clock();vector<int>v1(NUM);time_t end1 = clock();time_t begin2 = clock();vector<int>v2;v2.resize(NUM);time_t end2 = clock();time_t begin3 = clock();vector<int>v3;v3.reserve(NUM);// v3.resize(NUM); // 在加一个resize,时间消耗基本无差别time_t end3 = clock();cout << "init,    time: " << end1 - begin1 << endl;cout << "resize,  time: " << end2 - begin2 << endl;cout << "reserve, time: " << end3 - begin3 << endl;
}

这里是引用

  • 结果
    声明位置设置大小,以及使用resize、reserve时间消耗差不多,reverse用时略小,因为不用初始化数据。

  • 结论
    数据量在百万以内差别不大,如果后面需要输入数据,推荐使用resize,至于原因请看第四个测试用例。


4. vector赋值操作


#define NUM 10000000void test_time_4()
{time_t begin1 = clock();vector<int>v1; // 初始不设置大小for (int i = 0; i < NUM; ++i){int t = i;v1.push_back(t);// 模拟: cin >> num;//       v.push_back(num);}time_t end1 = clock();time_t begin2 = clock();vector<int>v2(NUM);for (int i = 0; i < NUM; ++i){v2[i] = i;// 模拟:cin >> v[i];}time_t end2 = clock();cout << "t - v[i], time: " << end1 - begin1 << endl;cout << "v[i],     time: " << end2 - begin2 << endl;
}

在这里插入图片描述

  • 结果
    调用push_back消耗很大 – 10倍以上

  • 结论
    不推荐借用中间变量后调用push_back,
    推荐直接使用 v[i]接收数据


5. 遍历:下标和迭代器


#define NUM 100000000 void test_time_5()
{vector<int>v1(NUM);for (int i = 0; i < NUM; ++i) v1[i] = i;// 测试下标遍历和迭代器遍历的速度time_t begin1 = clock();size_t size = v1.size();for (size_t i = 0; i < size; ++i) v1[i] = 0;time_t end1 = clock();/*  // 范围for的底层实现使用的迭代器vector<int>::iterator it = v1.begin();while (it != v1.end()){*it = 0;++it;}*/time_t begin2 = clock();for (auto& e : v1) e = 0;time_t end2 = clock();cout << "v1[i],    time: " << end1 - begin1 << endl;cout << "iterator, time: " << end2 - begin2 << endl;
}

这里是引用

  • 结果
    debug条件下,迭代器访问的速度要快很多很多 – 10倍以上;
    release条件下,访问速度相差不大。

  • 结论
    推荐在能使用迭代器的条件下尽量使用迭代器访问,既范围for
    那么什么时候适合使用? – 不需要使用下标的情况下。


总结

  1. for循环中如果使用到成员变量(如size()),作为判断,十分推荐将该值保存到一个临时变量,之后使用临时变量来代替它进行判断,
    否则调用多次进行函数调用会拖慢CPU运算速度;
  2. 声明容器变量是,是否初始化大小都可以,因为在任何地方都一样,当然如果需要给容器数据初始化,如果不是一定要使用某些值,不建议初始化为非0值;
  3. vector添加成员时,十分推荐先开好空间,之后直接通过下标( v[i] )进行赋值;如果借用一个临时变量,再进行push_back()也会大大拖慢cpu指向速度;
  4. 遍历容器时,如果我们不需要使用下标,就十分推荐使用范围for

以上的建议都是针对数据量大的情况下使用的,百万、千万以上的量级,
如果平时使用,100、10000等小量级则差别不大,
不过,好习惯早早养成还是很有必要的,希望本文可以为有需要的朋友提供帮助。




http://www.ppmy.cn/news/84015.html

相关文章

成功加冕!用友大易获评2023最佳招聘管理软件供应商

人力资源服务业旗帜性商业奖项2023金帜奖(HRFLAG AWARDS)颁奖典礼于近日隆重举行。经过3个月的评选&#xff0c;用友大易从615家人力资源服务机构中脱颖而出&#xff0c;最终荣获「2023最佳招聘管理软件供应商」奖项。 2023金帜奖(HRFLAG AWARDS)是人力资源服务行业旗帜性的商业…

PMP考试都是什么题?

PMP新版大纲加入了ACP敏捷管理的内容&#xff0c;说是敏捷混合题型占到了 50%&#xff0c;但是这次318的考试&#xff0c;敏捷题占了大半&#xff0c;都说敏捷和情景快要占到80%-90%。 所以有友友说开了四个小时盲盒&#xff0c;题目读不懂&#xff0c;或者觉得4个选项都不对或…

Redhat7.3linux系统防火墙命令总结

在Linux系统部署皕杰报表后&#xff0c;需要关闭防火墙或者开放报表工具使用的端口&#xff0c;才能通过浏览器访问报表。 在linux中如何关闭防火墙或开启端口呢&#xff1f;基本上是基于命令操作。通过几天的实践&#xff0c;总结了有关防火墙的操作命令&#xff0c;现记录如…

从绿色节能趋势看存储资源盘活系统HBlock

数据中心约超过一半的成本是电费&#xff0c;数据存储系统作为数据中心三大件之一&#xff0c;能耗也约占三分之一&#xff0c;面对非结构化数据量的快速增长挑战&#xff0c;以及国家对数据中心绿色节能要求的提高&#xff0c;分布式存储的绿色节能愈来愈加重要。 分布式存储…

本地vue搭建的web网站项目app如何发布到互联网?

对于非专业人来说&#xff0c;提到 Vue并不熟悉。Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建。 简单来说&#xff0c;Vue是干什么用的呢&#xff1f;Vue通过提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用…

如何利用Python中的pymysql库来操作Mysql数据库,看这篇就够啦~

为了使python连接上数据库&#xff0c;你需要一个驱动&#xff0c;这个驱动是用于与数据库交互的库&#xff0c;本文是向大家介绍了如何利用python中的pymysql库来操作mysql数据库。 1、什么是pymysql&#xff1f; pymysql是从python连接到mysql数据库服务器的接口&#xff0c…

LiveGBS GB28181流媒体平台中如何根据各种应用场景提供不同播放权限,满足用户自定义各种播放权限

随着目前对信息安全的越来越重视&#xff0c;视频监控领域的视频流也需要做各种安全策略。视频监控流流媒体平台输出的直播流需要做权限限制&#xff0c;只允许哪些IP访问、只允许哪些用户访问等等各种权限限制。为了满足不同用户不同场景各种不同的播放权限需求&#xff0c;Li…

Three.js教程:模型对象旋转平移缩放变换

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 其他系列工具&#xff1a; NSDT简石数字孪生 模型对象旋转平移缩放变换 点模型Points、线模型Line、网格网格模型Mesh等模型对象的基类都是Object3D&#xff0c;如果想对这些模型进行旋转、缩放、平移等操作&#xff0c;如…