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;
}