欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++基础组件性能对比测试(1)双向队列std::deque和libuv队列

程序员文章站 2024-03-18 08:49:46
...

 

libuv中提供了一组宏,非常的简短,并且在放在了queue.h中,直接拷贝过来引用就可以对普通的类连接成一个队列,这里对比一下QUEUE和标准库中的std::deque的性能差别:

有如下几种解决方案:

1)libuv链接基础结构体或者类,自己管理了内存和指针,

2)std::deque存储对象实例,不需要关心内存

3)std::deque存储裸指针,需要自己释放内存

4)std::deque存储智能指针,不需要关心释放

5)std::deque存储半智能对象(继承enable_shared_from_this)

第一组测试:对比生成裸指针的简单对象以及智能指针对象的效率,发现差别比较大:

测试结果如下:

生成方法 10000个对象耗时(ms) 速度对比
简单对象 9 最快
智能指针 17.5 1.7倍时间
智能对象 22 2.2倍时间

 

代码如下:其中计时的类请参考我以前 的文章

struct Student {
	Student(int a, const char * s) :age(a), name(s)
	{
	}

	Student() = default;
	QUEUE node;
	int age;
	std::string name;
	
};

class StudentAuto : public enable_shared_from_this<StudentAuto>
{
public:
	StudentAuto(int a, const char * s) :age(a), name(s)
	{
	}

	StudentAuto() = default;

	std::shared_ptr<StudentAuto> getptr() {
		return shared_from_this();
	}

	~StudentAuto()
	{
		//std::cout << "析构StudentAuto" << endl;
	}
	QUEUE node;
	int age;
	std::string name;

};

void test5()
{
	Timer timer1;
	timer1.start();

	// 内存泄露
	Student * it = nullptr;
	for (int i = 0; i < 10000; i++)
	{
		it = new Student(i+1, "robin");
	}

	auto duration1 = timer1.stop_delta<std::milli>();
	std::cout << "生成10000 简单实体(ms): " << duration1 << endl;

	timer1.start();

	std::shared_ptr<Student> ptr[10000];
	for (int i = 0; i < 10000; i++)
	{
		ptr[i] =  make_shared<Student>(i + 1, "robin");
		//std::shared_ptr<Student> it = make_shared<Student>(i + 1, "robin");
	}

	auto duration2 = timer1.stop_delta<std::milli>();
	std::cout << "生成10000 智能实体(ms): " << duration2 << endl;
}

 

第二组对比:将各种对象插入2种队列测试

结果如下:

执行方法 10000个操作耗时(ms) 结论
已有简单对象插入UV队列 0.045 快,忽略不计
已有简单对象头部弹出UV队列 0.0611 快,忽略不计
生成简单对象插入UV队列 9 耗时在生成对象
     
std::deque指针尾部插入裸指针 7.5  
std::deque头部弹出裸指针 7.4  
std::deque尾部emplace_back简单对象 19  
std::deque头部弹出简单对象 14  
std::deque尾部生成并插入智能指针 24 不如直接插入对象

结论:

1)高并发服务器可以考虑使用LIBUV的队列管理,自己使用内存池来管理内存块;

2)普通的应用可以考虑使用std::deque直接管理对象,比插智能指针块

代码大概如下:


// 系统忙
//插入UV队列(ms):0.1168
//头部弹出(ms): 0.1078
//插入std::deque(ms): 20.5516
//弹出std::deque(ms): 32.1022

// 空闲
//插入UV队列(ms):0.045
//头部弹出(ms): 0.0611
//插入std::deque(ms): 7.4969
//弹出std::deque(ms): 7.3878
void test1()
{
	Student * students = new Student[10000];
	Student * it = students;
	for (int i = 0; i < 10000; i++)
	{
		it = students + i;
		it->age = i + 1;
		it->name = "robin";
	}

	Timer timer1;
	timer1.start();

	// 在UV插入信息
	QUEUE queue;
	QUEUE_INIT(&queue);

	for (int i = 0; i < 10000; i++)
	{
		it = students + i;

		QUEUE_INIT(&(it->node));
		QUEUE_INSERT_TAIL(&queue, &(it->node));
	}



	auto duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入UV队列(ms):" << duration1 << endl;

	// 头部弹出
	QUEUE *p;
	timer1.start();
	for (int i = 0; i < 10000; i++)
	{
		p = QUEUE_HEAD(&queue);
		if (p != &queue)
		{
			QUEUE_REMOVE(p);
		}
	}
	duration1 = timer1.stop_delta<std::milli>();
	std::cout << "头部弹出(ms): " << duration1 << endl;

	// 测试std::deque
	timer1.start();
	std::deque<Student *> studentQue;

	for (int i = 0; i < 10000; i++)
	{
		it = students + i;
		studentQue.push_back(it);
	}

	duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入std::deque (ms): " << duration1 << endl;

	timer1.start();
	for (int i = 0; i < 10000; i++)
	{
		studentQue.pop_front();
	}
	duration1 = timer1.stop_delta<std::milli>();
	std::cout << "弹出std::deque (ms): " << duration1 << endl;

	// 取出头测试
	/*QUEUE *p;
	p = QUEUE_HEAD(&queue);
	p = QUEUE_NEXT(p);
	Student *first_stu = QUEUE_DATA(p, struct Student, node);*/

	/**
	* Should output the name of wesley.
	*/
	/*printf("Received first inserted Student: %s who is %d.\n",
		first_stu->name.c_str(), first_stu->age);
*/
/*QUEUE_FOREACH(p, &queue) {
	Student *tmp = QUEUE_DATA(p, struct Student, node);
	cout << "name: " << tmp->name << " age: " << tmp->age << endl;

}*/

	delete[] students;
}
// 系统忙
//插入UV队列(ms):17.3848
//插入std::deque(ms): 50.7232
//弹出std::deque(ms): 46.7094

// 系统空闲
//插入UV队列(ms):9.0955
//插入std::deque(ms): 19.8008
//弹出std::deque(ms): 14.6486
void test2()
{

	// 在UV插入信息

	Timer timer1;
	timer1.start();

	Student * students = new Student[10000];
	Student * it = students;
	for (int i = 0; i < 10000; i++)
	{
		it = students + i;
		it->age = i + 1;
		it->name = "robin";
	}
	QUEUE queue;
	QUEUE_INIT(&queue);

	for (int i = 0; i < 10000; i++)
	{
		it = students + i;

		QUEUE_INIT(&(it->node));
		QUEUE_INSERT_TAIL(&queue, &(it->node));
	}

	auto duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入UV队列(ms):" << duration1 << endl;
	/
	timer1.start();
	std::deque<Student> studentQue;
	for (int i = 0; i < 10000; i++)
	{
		studentQue.emplace_back(i+1, "robin");
	}

	duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入std::deque (ms): " << duration1 << endl;

	timer1.start();
	for (int i = 0; i < 10000; i++)
	{
		//cout << studentQue[0].age << endl;
		studentQue.pop_front();
	}
	duration1 = timer1.stop_delta<std::milli>();
	std::cout << "弹出std::deque (ms): " << duration1 << endl;

	delete[] students;
}

//插入10000std::deque智能指针(ms): 64.094
//插入10000std::deque对象(ms): 55.6962
using StudentPtr = std::shared_ptr<Student>;
void test3()
{

	Timer timer1;
	timer1.start();
	
	std::deque<StudentPtr> studentQ;
	for (int i = 0; i < 10000; i++)
	{
		studentQ.push_back(std::make_shared<Student>(i + 1, "robin"));
	}
	auto duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入10000std::deque智能指针 (ms): " << duration1 << endl;

	timer1.start();
	std::deque<Student> studentQue;
	for (int i = 0; i < 10000; i++)
	{
		studentQue.emplace_back(i + 1, "robin");
	}

	duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入10000std::deque对象(ms): " << duration1 << endl;

}

void test4()
{
	// 在UV插入信息

	Timer timer1;
	timer1.start();

	QUEUE queue;
	QUEUE_INIT(&queue);

	for (int i = 0; i < 10000; i++)
	{
		std::shared_ptr<StudentAuto> it = make_shared<StudentAuto>(i + 1, "robin");

		QUEUE_INIT(&(it->node));
		QUEUE_INSERT_TAIL(&queue, &(it->node));
	}

	auto duration1 = timer1.stop_delta<std::milli>();
	std::cout << "插入10000智能对象UV队列(ms):" << duration1 << endl;
}