对象流化与基于内存的流实现

烽驿2009开源实时通信平台 源码获取:svn checkout http://fy2009.googlecode.com/svn/trunk/ fy2009-read-only 

 

将一个对象转换成字节流形式,或从这种字节流中还原出对象是通信及存储类软件中最普遍的操作之一。对该类操作的称谓则五花八门:编码/解码(Encode/Decode);序列化/反序列化(Serialize(TRUE/FALSE),MFC的叫法); 列集/反列集(Marshal/Unmarshal, Microsoft COM组件技术的叫法)及持久化(Persist) 等等。
我们通常所说的对象多指分配在内存中的Class实例,或称为“活动对象”,只存活于进程生存期内,进程结束,活动对象则随之消亡。为了存储或通信等目的,我们时常需要将活动对象长期保存或从A机器传送到B机器,这要求我们将活动对象转换成可在进程外存在的形式,对该操作的一般性描述就是这里所说的对象流化。之所以叫流化,是因为在进程外承载对象的介质(Medium)通常都提供按字节顺序读写的特性,即流操作,如文件操作,Socket连接等等,因此,可以用统一抽象的流(Stream)去描述这类介质,用对象流化去统一描述对象存储及传输等需求。
class stream_it : public lookup_it
{
public:
 virtual uint32 read(int8* buf, uint32 len)=0;
 virtual uint32 write(const int8* buf, uint32 len)=0;
};
该接口刻画出所有按字节顺序读写的介质,并不关心具体实现在磁盘文件上还是Socket连接上。显然,为了某些目的,你也可以将其实现在内存中,而且,在工程实践中经常这样做。
class random_stream_it : public stream_it
{
public:
 virtual uint32 seek(int8 option, int32 offset)=0;
};
该接口刻画出支持随机读写的介质,如随机读写文件或实现在内存中的流介质。
本项目目前提供了两者基于内存的流实现,一种由调用者指定内存块的固定尺寸的流介质
fast_memory_stream_t,支持随机读写,优点是简单,高效,缺点是尺寸固定,不灵活,调用者必需大体知道流化操作的最终尺寸; 另一个自动分配内存的可伸缩内存流介质memory_stream_t,同样支持随机读写,且调用者不必知道最终流化尺寸,它会在必要时自动分配新的内存块,为保持效率,内存分配并不会导致现有内容的Copy,其内部结构是一个内存块列表,而不是只有一个连续内存块,因结构较前者复杂,管理开销相应较大,效率不如前者高。另外,为在Linux下和readv/writev高效配合,该实现还提供了直接用写满数据的内存块列表填写struct iovec结构的函数。
上述两个流接口很好地刻画了这类介质的读写特性,但接口调用缺乏形式美,大家都知道C++中的"<<",">>"流操作运算符,很有形式美,为了把程序写得更美,stream_adaptor_t对stream_it的接口操作进行了适配(Adapt),对常用类型定义了流操作运算符,更重要的是提供了字节序支持,做通信软件的人都知道所谓的“主机字节序”和“网络字节序”,如果源端和目标端的主机字节序不同,简单流化的对象在目标主机上是不能还原的,因此,要求在通信介质上传输的对象都用网络字节序,接收端再还原成自己的主机字节序,实践证明字节序转换工作并非微不足道,尤其通信数据量较大时更是这样,显然,在一个多数主机字节序相同且和网络字节序相反的通信网络中,基于网络字节序的通信并非最优,作为基础的流服务不强行设定字节序,而由调用者指定是个不错的选择,stream_adaptor_t允许调用者指定字节序。

 

性能测试:
测试条件:Windows XP 2002--Intel(R) Celeron(R) CPU 2.66GHz
          Linux 2.4.18-14--Intel(R) Celeron(R) CPU 2.00GHz

1.基准测试1:将10MB的数据一次Copy一个字节,Copy到一块预分配的连续内存中
  Linux下用时:658ms; Windows下用时:125ms
2.基准测试2:将10MB数据逐字节放到std::deque中(并不是stream的等价操作,只是用作性能对比)
  Linux下用时:328ms; Windows下用时:2813ms
3.fast_memory_stream_t性能:操作同上
  Linux下用时:890ms; Windows下用时:1219ms
4.memory_stream_t性能:操作同上
  Linux下用时:1053ms; Windows下用时:1406ms

结论:相对于裸内存操作,Stream操作有一定的性能损耗,但除非极简单的场合,裸内存操作通常并不能代替流操作,因此,这种操耗通常是不得不付的代价,但知道这个事实仍然是重要的,如果你确信流操作不会给你带来明显的好处,那就毫不犹预地直接Copy内存吧。
正如预期的那样,fast_memory_stream_t要比memory_stream_t高效,但缺点也如前面所述,同样,你确信自己可以准确预测流化尺寸的话,那就用fast_memory_stream_t吧,否则,memory_stream_t仍然是相当高效的选择。另外,随裸内存Copy处,Windows的表现全部不如Linux,尤其是Windows的deque表现让人“忍无可忍”,奉劝一句,如果你不能肯定自己真地需要std::deque的特性,那就别用它了吧,当然Windows下别的STL容器也许表现更差也未可知,不过本文未做测试。
另外,通过stream_adaptor_t接口的操作性能较直接流操作性能约下降10%,同样,后者提供的便捷性也许使你无法抗拒,尤其需要指定字节序时,更是这样。但不幸的是在Windows下,后者的性能下降居然高达100%,噢!My God!我还能为你做什么呢?如果可能,还是别让Server跑在Windows上了吧。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值