boost::bind与虚函数,运行效率,谁高??100分!有答案了立马结贴给分.

knift1128 2009-04-01 01:43:55
最近在看boost,从设计角度来讲很喜欢boost::lambda,boost::function,boost::bind , 这三者结合好,完全可以更优雅的实现"晚绑定",也就是OOP里多态要的效果...

就是不知从纯效率来讲boost::bind高还是虚函数高呢??因为我们都知道虚函数多一个VTBL,多一次寻址,效率是赶不上普通函数的...不知道相比boost:bind,谁更快些?
...全文
718 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
JCIphone 2012-10-15
  • 打赏
  • 举报
回复
试了一下,debug下boost::bind差太多,但是release下都差不多。


没有whoke说的2.5倍吧


学习了。。。
emptyness 2011-08-29
  • 打赏
  • 举报
回复
boost::bind 太牛了.release效果非常好. 又试了下构造和析构 ,可惜不好判断release版本,是否优化了我的局部变量构造. 感觉效率可以接受.
whoke 2009-11-11
  • 打赏
  • 举报
回复
楼上的都没有用Release版本测试吧。
Release版本的测试结果是虚函数是bind方式的2.5-3倍。
caocheng8230 2009-10-28
  • 打赏
  • 举报
回复
不感用boost::binding了,
受到启发了.
knift1128 2009-04-03
  • 打赏
  • 举报
回复
看来用boost的不多~~~~
机智的呆呆 2009-04-03
  • 打赏
  • 举报
回复
std::bind1st使用过程中要生成几个临时的对象,通过对象调用operator(),所以理论上讲比虚函数效率低,
没看过boost::bind,感觉应该类似把
knift1128 2009-04-03
  • 打赏
  • 举报
回复
同时还看出来虚函数调用代价非常小,同样的代码,和普通函数只有1%-2%之间差距.....看来还是虚函数靠谱.
knift1128 2009-04-03
  • 打赏
  • 举报
回复
昨天我也写了一段程序测试了~~boost::bind在MAX_LOOP各个数量级下都要比virtual function慢7-8倍~~~

郁闷~~~这就是boost华丽的代价.


#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <Windows.h>
#include <stdio.h>
#define MAX_LOOP 10000000
#define CONST_NUM 3

typedef boost::function<void()> task;
class VBase
{
public:
virtual void say();
};

class VChild:public VBase
{
public:
VChild(int);
void say();
private:
int count;
};

class BChild
{
public:
BChild(int);
void say();
private:
int count;
};

void VBase::say()
{

}

VChild::VChild(int count)
{
this->count = count;
}
void VChild::say()
{
this->count = this->count*CONST_NUM;
this->count = this->count/CONST_NUM;
this->count = this->count+CONST_NUM;
this->count = this->count-CONST_NUM;
}

BChild::BChild(int c)
{
this->count = c;
}

void BChild::say()
{
this->count = this->count*CONST_NUM;
this->count = this->count/CONST_NUM;
this->count = this->count+CONST_NUM;
this->count = this->count-CONST_NUM;
}

void runVFunction(VBase *pObject)
{
int start = ::GetTickCount();
for(int i=0 ; i < MAX_LOOP ;++i)
{
pObject->say();
}
printf("virtual function :%ims\n",(::GetTickCount()-start));
}

void runBind(task func)
{
int start = ::GetTickCount();
for(int i=0 ; i < MAX_LOOP ;++i)
{
func();
}
printf("boost::bind :%ims\n",(::GetTickCount()-start));
}

int main()
{
VChild *vObj = new VChild(10);
BChild *bObj = new BChild(10);
runVFunction(vObj);
runBind(boost::bind(&BChild::say,bObj));
system("pause");
return 0;
}
zhuxueling 2009-04-03
  • 打赏
  • 举报
回复

//
// bind_vir_test.cxx
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// file create 2009-04-03
// last update 2009-04-03
//
// Bugs Report <zhuxueling@live.cn>
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#include<traxex/Function.hpp>
#include<traxex/ToolKit.hpp>
#include<iostream>
using namespace Traxex;

long long int i;

struct B{
virtual void do_someting() = 0;
};

struct T:public B{
void do_someting(){
i *=2;
i /=2;
i +=2;
}
};

int test0(){
double time_start = time_now();
T t;
for( int i = 0; i < 100000000; ++i){
t.do_someting();
}
double time_end = time_now();
double time_used = time_end - time_start;
std::cout << "time_use0: " << time_used << std::endl;
}

int test1(){
double time_start = time_now();
T t;
function<void()> func = bind( &T::do_someting, &t);
for( int i = 0; i < 100000000; ++i){
func();
}
double time_end = time_now();
double time_used = time_end - time_start;
std::cout << "time_use1: " << time_used << std::endl;
}

int test2(){
double time_start = time_now();
T t;
for( int i = 0; i < 100000000; ++i){
function<void()> func = bind( &T::do_someting, &t);
func();
}
double time_end = time_now();
double time_used = time_end - time_start;
std::cout << "time_use2: " << time_used << std::endl;
}

int test3(){
double time_start = time_now();
B *t = new T();
for( int i = 0; i < 100000000; ++i){
t->do_someting();
}
double time_end = time_now();
double time_used = time_end - time_start;
std::cout << "time_use3: " << time_used << std::endl;
}

int main(){
test0();
test1();
test2();
test3();
}

zhuxueling 2009-04-03
  • 打赏
  • 举报
回复
我对一个小函数调用1亿次,得到下面的数据。

time_use0: 1.63758 直接调用
time_use1: 7.25978 调用binder得到的functor
time_use2: 33.8029 先bind,之后调用binder得到的functor
time_use3: 1.70608 使用虚函数


可以看出,在用时上,1亿次调用中,

1。虚函数会多出 0.07秒左右,多出的时间用在虚函数表上。
2。对bind包装后的functor调用会多出6.6秒左右,多出的时间会在自动封包,拆包函数上。
3。如果构造了一个functor,之后调用之,时间会更长,32.2秒左右。多时的时间是functor的构造与析构,封包与拆包。

___________________________________________
Linux linux 2.6.28-ARCH , gcc (GCC) 4.3.3
ypb362148418 2009-04-01
  • 打赏
  • 举报
回复
我觉得虚函数快一些
老邓 2009-04-01
  • 打赏
  • 举报
回复
很多时候我更喜欢解藕,而牺牲效率。
老邓 2009-04-01
  • 打赏
  • 举报
回复
如果是VS9SP1的话,应该是tr1::bind了吧。
没必要用boost。
喜欢tr1::bind,更喜欢其解藕!
knift1128 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 taodm 的回复:]
能不能举个bind和虚函数可以互替的场合?
[/Quote]
重新整理了一下这个伪代码..

虚函数版

class BaseProtocol
{
public:
virtual void onData(void *pData,sizt_t len);
};
class ServerProtocol:baseProtocol
{
public:
virtual void onData(void *pData,sizt_t len)
{
//有数据来了~
}
virtual void onAccept(socket *pClient)
{
//有连接来了~
}
};

//网络处理层,形参是基协议类指针,OOP的多态
void core(BaseProtocol *p)
{
//这里socket处理
while(1)
{
int n = epoll_wait(.....);
//有连接了就调 p->onAccept
//有数据了就调 p->onData
}
}
int main()
{
//这里我要处理ServerProtocol这个协议
ServerProtocol *pService = new ServerProtocol();
core(pService);//工作 传的是ServerProtocol指针
}




boost::bind版

//这个是boost::function对象,类似C#的委托.
typedef boost::function<void (socket *)> acceptHandle;
typedef boost::function<void (void *,size_t)>dataHandle;
class BaseProtocol
{
public:
//普通成员函数即可
void onData(void *pData,sizt_t len);
};
class ServerProtocol
{
public:
void onData(void *pData,sizt_t len)
{
//有数据
}
void onAccept(socket *pClient)
{
// 有连接
}
};
//这里传boost::function ,核心思想是,只关心能调用的东西的"样子"
void core(acceptHandle ah,dataHandle dh)
{
//这里处理网络
while(1)
{
int n = epoll_wait(.....);
//有连接了就 直接 ah(....);
//有数据了就调 dh(....);
}
}
int main()
{
//这里我要处理ServerProtocol这个协议
ServerProtocol *pService = new ServerProtocol();
core(boost:bind(&ServerProtocol::onAccept,pService),boost::bind(&ServerProtocol::onData,pService,_1,_2));//工作 boost::bind把协议对象,函数联系起来,当然core是不关心这些的,他只关心"样子"
}




taodm 2009-04-01
  • 打赏
  • 举报
回复
那你实际测一下不就知道效率了。
knift1128 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 taodm 的回复:]
能不能举个bind和虚函数可以互替的场合?
[/Quote]

你要封装一个Socket网络框架.
虚函数的"晚绑定":

class BaseProtocol
{
public:
virtual void onData(void *pData,sizt_t len);
virtual void onAccept(socket *pClient);
};
class ServerProtocol:baseProtocol
{
public:
virtual void onData(void *pData,sizt_t len){}
virtual void onAccept(socket *pClient){}
};
//
void core(BaseProtocol *p)
{
//这里socket处理
while(1)
{
int n = epoll_wait(.....);
//有连接了就调 p->onAccept
//有数据了就调 p->onData
}
}
int main()
{
//这里我要处理ServerProtocol这个协议
ServerProtocol *pService = new ServerProtocol();
core(pService);//工作
}




用boost::bind,无需虚函数,也无需要继承...协议与协议完全解藕。

typedef boost::function<void (socket *)> acceptHandle;
typedef boost::function<void (void *,size_t)>dataHandle;
class BaseProtocol
{
public:
void onData(void *pData,sizt_t len);
void onAccept(socket *pClient);
};
class ServerProtocol
{
public:
void onData(void *pData,sizt_t len){}
void onAccept(socket *pClient){}
};
void core(acceptHandle ah,dataHandle dh)
{
//这里处理网络
while(1)
{
int n = epoll_wait(.....);
//有连接了就 直接 ah(....);
//有数据了就调 dh(....);
}
}
int main()
{
//这里我要处理ServerProtocol这个协议
ServerProtocol *pService = new ServerProtocol();
core(boost:bind(&ServerProtocol::onAccept,pService),boost::bind(&ServerProtocol::onData,pService,_1,_2));//工作
}



eff c++好像是第36条吧,专门有讲这个
taodm 2009-04-01
  • 打赏
  • 举报
回复
能不能举个bind和虚函数可以互替的场合?
  • 打赏
  • 举报
回复
当然是虚函数了,只是多了一次内存访问
至于bind则不知道多多少过程了
liliangbao 2009-04-01
  • 打赏
  • 举报
回复
好像虚函数更快一点。
表在编译时已建立好
xuhb95083023 2009-04-01
  • 打赏
  • 举报
回复
bind说白了就是一个有状态的函数对象,要实现类似多态的效果的情况下,他的这个状态是一个成员函数指针,仅此而已
加载更多回复(4)

64,386

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧