测试目标
测试在成员个数不断递增的情况下,set、vector与list的构造与排序的耗时变化,找出set耗时连续超过其他容器耗时的成员个数
测试方式
set使用直接插入
vector使用assign构造并使用全局sort排序
list使用assign构造与成员sort的排序之间
比较的是耗时时间大小,对耗时的具体值不关心,因为不同的机器配置不一样
测试结论
由于设定的连续超过次数不同,得到的成员个数值也不同,并且随着连续超过上限的增加而增加,因此现在得到的成员个数值并不准确,如:
在连续超过上限为10时,成员个数最大在700左右
在连续超过上限为20时,成员个数最大在2000左右
但有一点可以肯定:set的边插入边排序效率,没有vector与list的赋值或排序高,如果有海量数据排序的情况,用vector或list的赋值后排序的性能相对于set比较好。
测试代码
// 主逻辑 main.cpp
#include "TimeConsume.h"
#include "Random.h"
#include <unistd.h>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <iostream>
#include <cstdint>
#include <string>
using namespace std;
// set耗时是否连续超出其他容器
bool is_continue_beyond(uint64_t vector_time, uint64_t list_time, uint64_t set_time, uint64_t beyond_num) {
static uint64_t s_beyond_num = beyond_num;
if (set_time > list_time && set_time > vector_time) {
--s_beyond_num;
} else {
s_beyond_num = beyond_num;
}
return s_beyond_num == 0;
}
int main(int argc, char** argv) {
uint64_t member_count_num = 0;
uint64_t member_add_num = 0;
uint64_t beyond_num = 0;
if (argc != 4) {
cout << "input: " << argv[0] << " member_start_num member_add_num beyond_num" << endl;
return -1;
} else {
member_count_num = strtoull(argv[1], NULL, 10);
member_add_num = strtoull(argv[2], NULL, 10);
beyond_num = strtoull(argv[3], NULL, 10);
}
uint64_t vector_time = 0;
uint64_t list_time = 0;
uint64_t set_time = 0;
while (!is_continue_beyond(vector_time, list_time, set_time, beyond_num)) {
vector<uint64_t > input_random_num; // 使用一样的随机数据
Random random;
random.SetRandomNum<vector<uint64_t> >(member_count_num, input_random_num);
// 构造排序函数
vector<uint64_t> monitor_vector; // 外部定义容器,防止构造析构带来的时间计算
auto vector_sort = [&]() {
monitor_vector.assign(input_random_num.begin(), input_random_num.end());
sort(monitor_vector.begin(), monitor_vector.end());
};
list<uint64_t> monitor_list;
auto list_sort = [&]() {
monitor_list.assign(input_random_num.begin(), input_random_num.end());
monitor_list.sort();
};
set<uint64_t> monitor_set;
auto set_sort = [&](){
monitor_set.insert(input_random_num.begin(), input_random_num.end());
};
// 统计排序时间
TimeConsume vector_time_consume(vector_sort);
TimeConsume list_time_consume(list_sort);
TimeConsume set_time_consume(set_sort);
vector_time = vector_time_consume.GetFnTime();
list_time = list_time_consume.GetFnTime();
set_time = set_time_consume.GetFnTime();
cout << "count:" << member_count_num<< "\t" << "vector_time:" << vector_time << "\t" << "list_time:" << list_time << "\t" << "set_time:" << set_time << endl;
sleep(0.5);
member_count_num += member_add_num;
}
return 0;
}
/*
TimeConsume.h
用于获得程序运行的时间消耗,支持函数对象(C++11新标准)
获得的耗时为微秒级
*/
#ifndef TIME_CONSUME_H
#define TIME_CONSUME_H
#include <sys/time.h>
#include <ctime>
#include <functional>
using std::function;
#define SEC_RATIO_MSEC 1000
#define SEC_RATIO_USEC (1000*SEC_RATIO_MSEC)
class TimeConsume {
public:
TimeConsume(const function<void()> &monitor_fn = [](){;})
: m_monitor_fn(monitor_fn) {
Clear();
}
~TimeConsume()
{;}
// 设置耗时监控的函数对象
inline function<void()> SetMonitorFn(const function<void()> &monitor_fn()) {
auto old_monitor_fn = m_monitor_fn;
m_monitor_fn = monitor_fn;
return old_monitor_fn;
}
// 记录开始监控的时间点
inline void Start() {
gettimeofday(&m_start, NULL);
}
// 记录结束监控的时间点
inline void End() {
gettimeofday(&m_end, NULL);
}
// 依据开始和结束监控的时间点,得到微秒级耗时
inline uint64_t GetIntervalTime() {
if ((m_end.tv_sec > m_start.tv_sec)
|| (m_end.tv_sec == m_start.tv_sec && m_end.tv_usec >= m_start.tv_usec)) {
return (m_end.tv_sec - m_start.tv_sec)*SEC_RATIO_USEC + (m_end.tv_usec - m_start.tv_usec);
} else {
return 0;
}
}
// 获得监控函数对象的微秒级运行耗时
inline uint64_t GetFnTime() {
Clear();
Start();
m_monitor_fn();
End();
return GetIntervalTime();
}
protected:
// 格式化内部相关值
inline void Clear() {
m_start.tv_sec = 0;
m_start.tv_usec = 0;
m_end.tv_sec = 0;
m_end.tv_usec = 0;
}
private:
struct timeval m_start;
struct timeval m_end;
function<void()> m_monitor_fn;
};
#endif
/*
Random.h
可以向STL 容器里填充指定个数的随机值,取值范围在[0-RAND_MAX],RAND_MAX为最大值的整数常量表达式。此值依赖实现。保证此值至少为32767
*/
#ifndef RANDOM_H
#define RANDOM_H
#include <ctime>
#include <iterator>
using std::inserter;
class Random {
public:
Random() {
srand(time(NULL));
}
~Random()
{;}
template <typename ContainerT>
inline void SetRandomNum(uint64_t count, ContainerT &container) {
auto iter = inserter(container, container.end());
for (uint64_t i = 0; i < count; ++i) {
iter = rand();
}
}
};
如果对测试有什么疑问或建议,欢迎大家来讨论
转载于:https://blog.51cto.com/zmh009/2071986