在写代码时,往往为了使用方便,将一些接口类设计为单例模式。
如果能够理清类之间的创建关系,最好将对象的指针传入要使用的对象中。
以下为同一台机器上进行的多次性能测试,性能差别还是比较明显的。
#include <stdlib.h>
#include <stdio.h>class A
{
public:A() = default;~A() = default;static A& get_instance(){static A my_intance;return my_intance;};void func(){printf("print func\n");}
};int main()
{// A a;int count = 1000000000;while (count-- > 0){A::get_instance().func();// a.func();}return 0;
}
测试结果:
单例模式测试结果
real 0m16.725s
user 0m16.540s
sys 0m0.180sreal 0m16.737s
user 0m16.561s
sys 0m0.170sreal 0m16.849s
user 0m16.684s
sys 0m0.160sreal 0m16.850s
user 0m16.686s
sys 0m0.160sreal 0m16.832s
user 0m16.667s
sys 0m0.160s
通过指针传递引用方式测试结果
real 0m15.821s
user 0m15.608s
sys 0m0.210sreal 0m15.932s
user 0m15.806s
sys 0m0.120sreal 0m16.218s
user 0m16.043s
sys 0m0.170sreal 0m16.061s
user 0m15.877s
sys 0m0.180sreal 0m16.008s
user 0m15.833s
sys 0m0.170s
10亿次输出单条log,性能差距将近10%
=======================
将上述创建A对象的方式用shared_ptr的方式,这效率能与原始指针的方式差距更大,约20%
测试程序:
#include <stdlib.h>
#include <stdio.h>
#include <memory>class A
{
public:A() = default;~A() = default;static A& get_instance(){static A my_intance;return my_intance;};void func(){printf("print func\n");}
};int main()
{auto p = std::make_shared<A>();int count = 1000000000;while (count-- > 0){// A::get_instance().func();// a.func();p->func();}return 0;
}
测试结果:
real 0m20.193s
user 0m19.970s
sys 0m0.220sreal 0m19.380s
user 0m19.207s
sys 0m0.160sreal 0m19.389s
user 0m19.215s
sys 0m0.170s
如果存在shared_ptr赋值给weak_ptr,在weak_ptr使用时,追加 expired判断 和 转换为shared_ptr,效率就低的更可怕。
部分程序(类A没有变动):
int main()
{auto p = std::make_shared<A>();std::weak_ptr<A> w_p = p;int count = 1000000000;while (count-- > 0){// A::get_instance().func();// a.func();if(!w_p.expired()){std::shared_ptr<A> sp = w_p.lock();sp->func();}}return 0;
}
测试结果:
real 1m2.789s
user 1m2.611s
sys 0m0.170sreal 1m2.371s
user 1m2.043s
sys 0m0.320sreal 1m3.127s
user 1m2.939s
sys 0m0.181s