C++ STL之前vecotr与list性能实测

C++ STL之vecotr与list性能实测

  • 前言
    • vector与list谁的速度更快?
    • 实验结束分析

前言

STL中vector用比较,list由于习惯原因基本没用,最近看了下list的用法,发现和vector用法基本相同,只是list示支持按下标索引元素,需要枚举器访问。
下面是经常说到vector和list的两种区域
vector
会自动增长的数组,内部是对数组的封装,最大的优势就是随机访问的能力,但是前端和中间对数据进行操作必然会引起数据块的移动, 这对性能影响是非常大的。
list
一个双向链表的实现,为了提供双向遍历的能力,list要比一般的数据单元多出两个指向前后的指针,list数据是链式存储,所以不能随机存取元素,它的优势在于任意位置添加 删除元素的速度。

问题
从上面简单描述,vector随机访问速度快,list插入和删除操作速度快。
但究竟什么情况用vector什么情况下用list(list按下标访问不是事,随便写个封装就行)呢?下面作一个简单实验探究,看看两者实际的访问、插入、删除、查询速度。
(ps: 笔者平时只用vector,没细究过两者差别,这里算补交一下作业~)

vector与list谁的速度更快?

这里先上代码,先说一下代码并不完全自己写,而在另一篇博主的代码基础上改的(现在真的是有点太懒了),但两个测试时间是完全自己写的。

代码原博客网址:https://blog.csdn.net/zhouzhenhe2008/article/details/77428743/

下面修改后的代码与实验性能的代码

主要代码

typedef struct info_s
{
    int nNumber;
    int arr[100];  //性能主测试点,对vecotr来说大小不同会带来移动时拷贝的性能不同
    bool operator==(struct info_s b) const
    {
        return this->nNumber == b.nNumber;
    }
    bool operator!=(struct info_s b) const
    {
        return this->nNumber != b.nNumber;
    }
    bool operator>=(struct info_s b) const
    {
        return this->nNumber >= b.nNumber;
    }
    bool operator<=(struct info_s b) const
    {
        return this->nNumber <= b.nNumber;
    }
    bool operator>(struct info_s b) const
    {
        return this->nNumber > b.nNumber;
    }
    bool operator<(struct info_s b) const
    {
        return this->nNumber < b.nNumber;
    }
}info_t;


#include "stdafx.h"
#include "VecotrListTest.h"
#include "OrangeTimeTest.h"
using namespace OrangeUtilities;

typedef std::list< info_t > list_t;
typedef std::vector< info_t > vector_t;

void append(list_t &List, info_t &info)
{
    //std::cout << "***append****" << std::endl;
    List.push_back(info);
}
void append(vector_t &List, info_t &info)
{
    //std::cout << "***append****" << std::endl;
    List.push_back(info);
}
void for_each(list_t &List)
{
    std::cout << "***for_each****" << std::endl;
    list_t::iterator iter;
    for (iter = List.begin(); iter != List.end(); iter++)
    {
        std::cout << iter->nNumber << std::endl;
    }
}
void del_end_info(list_t &List)
{
    std::cout << "***del_end_info****" << std::endl;
    if (!List.empty())
    {
        List.pop_back();
    }
}
void for_each_delete(list_t &List)
{
    list_t::iterator iter;
    for (iter = List.begin(); iter != List.end();)
    {
        std::cout << "delete before  iter->number:" << iter->nNumber << std::endl;
        iter = List.erase(iter);
        std::cout << "delete  after iter->number:" << iter->nNumber << std::endl;
    }
}
int insert_one(list_t &List, info_t &info, int iPlace)
{
    int i = 0;

    std::cout << "insert_one" << std::endl;
    if (iPlace < 0)
    {
        std::cout << "insert_one  param error" << std::endl;
        return -1;
    }

    list_t::iterator iter = List.begin();

    while (iter != List.end())
    {
        //std::cout<<" dump "<< (*iVector)<nNumber << std::endl;
            return 0;
        }
        i++;
        ++iter;
    }
    iter = List.insert(List.end(), info);
    return 0;
}

int insert_one(vector_t &List, info_t &info, int iPlace)
{
    int i = 0;

    std::cout << "insert_one" << std::endl;
    if (iPlace < 0)
    {
        std::cout << "insert_one  param error" << std::endl;
        return -1;
    }

    vector_t::iterator iter = List.begin();

    while (iter != List.end())
    {
        //std::cout<<" dump "<< (*iVector)<nNumber << std::endl;
            return 0;
        }

        i++;
        ++iter;
    }
    iter = List.insert(List.end(), info);
    return 0;
}
void find_one(list_t &List, info_t info)
{

    std::cout << "find_one" << std::endl;

    list_t::iterator iter;

    iter = std::find(List.begin(), List.end(), info);

    if (iter != List.end())
    {
        //std::cout << "find it" << std::endl;
    }
    else
    {
        //std::cout << "not find it" << std::endl;
    }
}

void find_one(vector_t &List, info_t info)
{

    std::cout << "find_one" << std::endl;

    vector_t::iterator iter;

    iter = std::find(List.begin(), List.end(), info);

    if (iter != List.end())
    {
        //std::cout << "find it" << std::endl;
    }
    else
    {
        //std::cout << "not find it" << std::endl;
    }
}
void Sort(list_t & List)
{
    std::cout << "Sort it" << std::endl;
    List.sort();
    for_each(List);
}
info_t ListAt(list_t &l, int index)
{
    list_t::iterator iter = l.begin();
    advance(iter, l.size()/2);
    info_t info;
    info.nNumber = iter->nNumber;
    return info;
}
info_t ListAt(vector_t &l, int index)
{
    vector_t::iterator iter = l.begin();
    advance(iter, l.size() / 2);
    info_t info;
    info.nNumber = iter->nNumber;
    return info;
}
void InsertAt(list_t &l, info_t &info, int index)
{
    list_t::iterator iter = l.begin();
    advance(iter, index);
    l.insert(iter, info);    
}
void InsertAt(vector_t &l, info_t &info, int index)
{
    vector_t::iterator iter = l.begin();
    advance(iter, index);
    l.insert(iter, info);
}
void DeleteAt(list_t &l, int index)
{
    list_t::iterator iter = l.begin();
    advance(iter, index);
    l.erase(iter);
}
void DeleteAt(vector_t &l, int index)
{
    vector_t::iterator iter = l.begin();
    advance(iter, index);
    l.erase(iter);
}

void TestList()
{
    list_t infoList;
    info_t info;
    int s = sizeof(info);
    memset(&info, 0, sizeof(info_t));

    int n = 1024 * 1024;

    TimeTest t;
    t.BeginCounter();
    for (int i = 0; i < n; i++)
    {
        info.nNumber = i;
        infoList.push_back(info);
    }
    int msec = t.EndCounter();
    std::cout << "Inser 1M data, time is " << msec << " ms" << std::endl;

    t.BeginCounter();
    info_t temp = ListAt(infoList, n / 2);
    std::cout << "The middel data[n/2] is " << temp.nNumber << std::endl;
    msec = t.EndCounter();
    std::cout << "access middle data, time is " << msec << " ms" << std::endl;

    t.BeginCounter();
    find_one(infoList, temp);
    std::cout << "find middle data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    insert_one(infoList, temp, n / 2);
    std::cout << "insert in middle data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    InsertAt(infoList, temp, n / 2);
    std::cout << "insert at in middle data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    infoList.push_back(temp);
    std::cout << "push back data, time is " << t.EndCounter() << " ms" << std::endl;
    
    t.BeginCounter();
    temp.nNumber = 999;
    DeleteAt(infoList, n / 2);
    std::cout << "delete data at middel, time is " << t.EndCounter() << " ms" << std::endl;
}

void TestVecotr()
{
    vector_t infoList;
    info_t info;
    int s = sizeof(info);
    memset(&info, 0, sizeof(info_t));

    int n = 1024 * 1024;

    TimeTest t;
    t.BeginCounter();
    for (int i = 0; i < n; i++)
    {
        info.nNumber = i;
        infoList.push_back(info);
    }
    int msec = t.EndCounter();
    std::cout << "Inser 1M data, time is " << msec << " ms" << std::endl;

    t.BeginCounter();
    info_t temp = ListAt(infoList, n / 2);
    std::cout << "The middel data[n/2] is " << temp.nNumber << std::endl;
    msec = t.EndCounter();
    std::cout << "access middle data, time is " << msec << " ms" << std::endl;

    t.BeginCounter();
    find_one(infoList, temp);
    std::cout << "find middle data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    insert_one(infoList, temp, n / 2);
    std::cout << "insert in middle data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    InsertAt(infoList, temp, n / 2);
    std::cout << "insert at in middle data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    infoList.push_back(temp);
    std::cout << "push back data, time is " << t.EndCounter() << " ms" << std::endl;

    t.BeginCounter();
    temp.nNumber = 999;
    DeleteAt(infoList, n / 2);
    std::cout << "delete data at middel, time is " << t.EndCounter() << " ms" << std::endl;
}
int main()
{
    TestList();
    std::cout << "-------------------------" << std::endl;
    TestVecotr();
     getchar();
    return 0;
}

实验结束分析

先简要介绍一下上面测试:
info_t 大小由int arr[100]决定,测试中分别100个元素和1000个元素作了测试,而list和vector大小则采集1M个元素作测试

arr[100] n=1M测试结果

Inser 1M data, time is 2451 ms
The middel data[n/2] is 524288
access middle data, time is 90 ms
find_one
find middle data, time is 169 ms
insert_one
insert in middle data, time is 413 ms
insert at in middle data, time is 89 ms
push back data, time is 0 ms
delete data at middel, time is 89 ms


Inser 1M data, time is 1937 ms
The middel data[n/2] is 524288
access middle data, time is 0 ms
find_one
find middle data, time is 37 ms
insert_one
insert in middle data, time is 372 ms
insert at in middle data, time is 27 ms
push back data, time is 0 ms
delete data at middel, time is 30 ms

arr[1000] n=1M测试结果

Inser 1M data, time is 3950 ms
The middel data[n / 2] is 524288
access middle data, time is 101 ms
find_one
find middle data, time is 219 ms
insert_one
insert in middle data, time is 423 ms
insert at in middle data, time is 99 ms
push back data, time is 0 ms
delete data at middel, time is 99 ms


Inser 1M data, time is 8565 ms
The middel data[n / 2] is 524288
access middle data, time is 0 ms
find_one
find middle data, time is 110 ms
insert_one
insert in middle data, time is 658 ms
insert at in middle data, time is 272 ms
push back data, time is 0 ms
delete data at middel, time is 280 ms

由上面的结果分析:
list在访问元素、插入、删除等操作耗时基本相同,并且在400MB数据和4000MB数据访问元素、插入、删除操作耗时没有太大变化
vector的元素访问速度非常快,基本可以忽略不计,在400MB数据下的插入、删除操作要优于list,但在4000MB速度下性能变差不如list

结论

小M没作更详细的研究实验,只能粗略的得出结论:
如果只需要访问和修改数据,不进行频繁的插入、删除等操作,那么用vector
如果数据变非常大(如上GB),并且需要频繁的插入、删除操作,那么用list
对于小型项目,数据量不大(100M以内)vector各方面比list性能要好

实验条件
OS: Windows 10 x64
内存:12GB
CPU: Intel Core I7-4700HQ
程序:64位

结束分割线-------------------------------------------------------------------------------------------
本次实验只在400MB和4000MB数据下进行了测试,没有连续性测试,只能得出粗略的结论,如有不当之处请各位路过的朋友不吝指正,大家一起进步

你可能感兴趣的:(C++,C++)