本帖最后由 VisualEleven 于 2011-10-12 22:49:06 编辑

解决方案 »

  1.   

    网络传输和内存管理是不同的
    网络上处理的是字节流
    自然不存在对齐的问题如果new一块内存然后分割成结构体结构体内部是会对齐的
    你说的地址不整齐是什么意思?
      

  2.   

     BYTE[1M]这种需要对其吗 ,一般都是结构体需要对齐的吧
      

  3.   

    结构体按CPU位数对齐存取结构体速度会较快, 但实际能够提升多少性能, 想知道一下有没有实际进行修改过的人的经验. 写入数据格式进行发送的时候, 有人喜欢用结构体, 有人不喜欢用结构体的(我就是其中一个), 不采用应该不存在这些问题吧? 但很经常会存在 把BYTE* buf, 在使用的时候是 *(DWORD32*)buf = 0x1234239F 的方式直接使用, 这样存不存在存取速度的问题?地址不整齐是指: 在x86下面, 地址不是4的整数倍, x64下面, 地址不是8的整数倍的意思, 这样会不会操作速度带来影响?
      

  4.   

    地址对齐,不用考虑(貌似不是我们考虑的),结构体的字节对齐,同一个结构体在不同字节对齐下,其大小可能是不一样的,用sizeof是好习惯;网络传输的是二进制流,和对齐没关系,要注意的是网络上的buf必须是连续的,本地则不一定是连续的,转换时注意bmp文件结构有个字节对齐,那个是人为规定的,必须遵守;
      

  5.   


    实际会有多少? 我在读写流的时候不用结构体的, 而是直接用变量的, 结构体只会用在链表里面, 而且没有强制用1BYTE对齐, 都是由编译器默认对齐值的. 
    唯一较为担心的是内存分配, 整个服务器的代码, 所有要用堆的地方, 都是用内存池来做的, 虽然结构体是按CPU位数对齐的, 但内存划分的时候, 虽然多少给多少而已, 这样在一块连续的内存块上分成了很多个结构体, 这样会不会导致结构体即使对齐了也读取缓慢?
      

  6.   

    http://topic.csdn.net/u/20101119/20/b8d70ead-c4da-41d4-98e3-70a44bbcbfc5.html以前讨论过这个话题
      

  7.   

    在网络编程上, 由于网络字节顺序的问题, 通常只能够按BYTE操作, 序列时不用结构体, 散列时也不用结构体, 是不是就不存在字节对齐的性能损失了?
      

  8.   

    http://topic.csdn.net/u/20101119/20/b8d70ead-c4da-41d4-98e3-70a44bbcbfc5.html以前讨论过这个话题
      

  9.   

    网络上传输的数据一般都不会传输对齐的数据,不然利用率太低
    但处理这些数据的时候,不对齐会导致CPU的浪费如何处理这两者之间的矛盾,楼下解答
      

  10.   

    这.字节对齐可以节约一点点buffer.  4字节对齐时,多种数据类型时混合的结构体就会出现浪费空间的问题.1字节对齐就可以充分利用空间.cpu上不太了解.应该没太大区别的.
      

  11.   


    这里会有我想要的答案了. 我想问的问题应该解决了. 也给一下我的见解:
    1. 只有在结构对齐, 并且首地址对齐的情况下, CPU才可以实现最快的存取速度. 任何一方不满足, 都会降低效率.2. 序列散列, 网络操作都只能够是按BYTE进行, 那么不采用结构体而直接用单一的变量来读取会是最快的.3. 内存池的使用, 只有在内存池内部所有结构体均为CPU默认对齐的方式, 并且在向其申请内存块时, 申请大小不满足 大小 % CPU默认对齐值 == 0 时, 进行补充相应的大小, 以实现所有的内存块首地址均为对齐值的倍数, 这样才能够实现最快的读写效率.谢谢各位协助
      

  12.   

    "内存管理上, 申请了一大块的new BYTE[1M], 然后把这个内存块按需要切割给每种结构体, 存不存在字节对齐的问题? 结构体当然是字节对齐的, 但是地址上, 并不是整齐的, 这样会不会带来性能损失?"不是性能损失这么小的问题,而是错误的数据
      

  13.   

    byte是一个数组,数组还需要啥对齐??
      

  14.   

    ☻☀♣♦♥♡♧☼☺☏⋚⋛⊱♀※&@№卐♂▤░▬☌↔㊣▔▏╱╲╱╲★■◆*•▪☉⊙⊕Θ❤✪¤☜☞‥♣
      

  15.   

    ☻☀♣♦♥♡♧☼☺☏⋚⋛⊱♀※&@№卐♂▤░▬☌↔✪✪✪✪❤㊣▔▏╱╲╱╲★■◆*•▪☉⊙⊕Θ❤✪¤☜☞‥♣
    为什么这些符号都能打出来···我自己做的WEB项目就不行啊
      

  16.   

    论坛是怎么存放我们发的特殊符号哦?我把这些特殊符号放到Oracle数据库全是???号啊··取出来就全是问号了···
      

  17.   

    你可以看看ipmessager的源代码,自己写个代码传文件对比一下试试
      

  18.   

    字节对齐后,CPU就不用花多一些指令去读取代码
      

  19.   

    楼主理解的还是不对,这个问题跟“结构体”没关系。是硬件体系结构的问题,要从指令上看,比如X86指令 mov eax,[ebx] 加入ebx指向一个非4字节自然对齐的地址,它花费的指令周期就比对齐的要多(具体多多少,intel有文档,我以前看过,总之是10倍左右的额外成本)。
    这跟你将你的C结构体放在内存哪里没什么关系,关键看你的结构体上域的存取,比如类似C代码: p->age=3 这类操作,看age的地址是不是自然对齐,如果是自然对齐,性能就没有损失。
      

  20.   

    而且,楼主貌似在写服务器代码,服务器一般会设计为多线程的程序,你在考虑内存分配的对齐问题时,还要注意CPU Cache行的问题,否则会出现伪共享,导致性能降低100倍。
      

  21.   

    在网络编程上, 由于网络字节顺序的问题, 通常只能够按BYTE操作, 序列时不用结构体, 散列时也不用结构体, 是不是就不存在字节对齐的性能损失了??
      

  22.   


    字节对齐是仅对内存而言的,因为仅对CPU体系结构对内存的访问而言。
      

  23.   

    要是做过symbian手机上程序(我忘了CPU类型是什么)也会知道,如果你读写地址不是自然对齐的,程序会崩溃。 X86只是降低性能,很不错了。
      

  24.   


    结构体是有关系的, new, malloc, HeadAlloc 这些操作, 分配的内存块首地址均是自然对齐的地址, 即:
    new BYTE[123] 还是 new StructA 或者 new ClassA, 所有这些Instance, 首地址均为自然对齐. 但假如StructA里面有BYTE, 或WORD, 或BYTE[123], 然后加上Push(1)的话, 就会导致结构体成员访问时, 存在非自然对齐的地址. 就算不是用new, 而是在栈空间里面也好, 只要结构是非自然对齐的, 那么即使首地址已经帮你对齐好, 成员访问的时候依旧会导致地址不对齐. 使用内存池来分配所有堆空间时, 申请的内存池, 首地址是自然对齐的, 但假如分割的时候不按自然对齐的方式, 那么即使结构体是自然对齐, 也依旧会导致二次访问取值的问题. 那个讨论过的贴子里面说得很清楚了. 只要访问的地址不是自然对齐, 就会导致二次访问取值.今天晚上我把服务器除了数据流那里只能够按BYTE操作以外, 其他地方都搞成对齐了, 总体的速度的确有点提升, 但只有3% ~ 4%左右的提升, 或者是因为我不喜欢用结构体来序列散列, 所以也就这么一点了..距离10万/s 并发, 目前在我的i5上还差20%, 可能换上i7能够上了.
      

  25.   

    网络通讯为什么不对齐不是因为这样效率高或字节序问题,是为了统一,因为你不知道连接你的机器和你的机器CPU位数是不是相同,实际上这样的效率的确是低一些,如果你能确定所有连接程序可以使用相同的对齐方式,可以直接把结构写到网络报文中,这样会比你不对齐要快,不信你可以测试一下
      

  26.   


    判断Client和Server字节顺序当然可以节省Server的顺序变换, 但直接用struct来写报文当然是可行的, 但却要客户端在接收的时候做很多判断的. 交互之前获了服务器字序和位数, 然后定义相应的struct和读取方式. 不过可惜的是, 让网络在每个数据包里面传送多几个B(为对齐的B)会导致更大的性能损失的. 几个B的预留空间对于本机的CPU和内存操作来说, 根本算不上时间和浪费, 但对于网络传送来说, 每个包都有几B浪费的时候, 这就问题大了. 所以, 现世的服务器, 用上struct写报文的, 都会是以BYTE对齐, 至于字节顺序来说, 既然都是按BYTE复制的话, 反过来复制来按顺序复制, 速度也是千万级别下都没有时间区别的, 所以不太推荐你说的方式.
      

  27.   

    各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况, 但是最常见的是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为 32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低 字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空间和时间的博弈。具体的性能相差多少,需要看cpu总线宽度和定义为几字节对齐。
      

  28.   


    就是说,当多个线程访问临近的地址空间的时候,比如struct {
       int a;
       int b;
    } object;线程1读域object.a,线程2写object.b这时可能会出现一个伪共享现象,因为object的域a和b很可能在一个Cache行上(Cache行是CPU缓存换入换出的最小单位),这个时候,核A上正在运行线程1,核B上正在运行线程2,而核B改动object.b的时候,CPU缓存协议机制就会把这个改动交给核A(因为核A正在关注这个Cache行),而这种关注是无效的,因为核A根本不关心object.a。这样一来,无论是核A对object的a域进行改动,还是核B对object的b域进行改动都会导致无效的CPU Cache协议行为,这就是伪共享现象,频繁的此类现象称为“Cache行乒乓”,这段Cache行就像乒乓球一样在两个核之间被推来推去。
      

  29.   


    学习了, 原来还有这种限制. struct会这样的话, 那么class也会发生这样的情况了. 也就是说必须把类里面异步访问的数据必须把间隔划分开来存放对吧. 有几个异步操作的类为了代码清晰的确是拼在一起写了.谢谢指教. 结贴.
      

  30.   


    对,就是说:各个线程的本地数据的地址之间要保持足够的间隔,以将他们隔离在不同的Cache行上(Cache行的大小跟CPU类型相关)。
      

  31.   

    我只懂结构体按CPU位数对齐存取结构体速度会较快额 。。
      

  32.   


    这点不太可能吧...汇编写得好与坏是能够直接影响的. 即使编译器有很大程度的优化, 但其实还是没有充分利用好CPU的寄存器的. 利用好寄存器, 运行速度可以接近CPU的频率, 但直接编译器编译出来的, 其实跟CPU的频率速度差很远的.
      

  33.   

    请问是这里的bmp文件所谓的字节对齐是指什么,什么意思呢?还有我看说JPEG码流是非字节对齐的,这个是什么意思呢?请赐教!
      

  34.   


    等 级: #81楼 得分:0回复于:2011-10-14 22:53:15
     引用 79 楼 luojian2003 的回复:性能问题要看你代码的运行情况,一般情况下不会成瓶颈的不是瓶颈的问题, 而是进行最大优化的问题 
      

  35.   


    有很多人, 或者说是我见过的项目里面吧, 特别是delphi, 写网络数据流的时候经常采用
    XXXX = package struct
     a: BYTE
     b: Interer
     ...
    end;然后外部直接操作这个struct, 像SOCKADDR那样, 要变换字节顺序的就先变换字节顺序, 最后就是直接把整个struct按字节复制进数据流. 
    然后在对方收到足够大小的数年流时, 直接把struct作为buffer, 从recv里面直接接收回来, 然后把整个数据变成struct, 然后操作struct. 这时候这个struct字节不对齐, 而外部就是经常通过这个struct来访问其内部成员的时候, 就降低速度了.这样写, 其实的确是带来很多方便和代码维护也较为容易的, 起码比起一个一个变量来写好看多了, 一种协议就是定义一个结构体. 只是我本人不喜欢这样写而已, 其实这样写的确代码是比较容易维护的. 我自己的协议都是没有定义任何结构体的, 都是直接按分析, 写注释, 直接写数据的. 所以不存在经常访问不对齐的struct的问题
      

  36.   

    字节对齐肯定能提高CPU处理数据的速度。
    网络上传输的结构体,是否字节对齐和你如何序列化有关,为了尽量减少传输的字节,应该是连续存放的。
    字节对齐是针对内存管理的,和网络传输没有无关。
    数据在网络中按什么方式传输完全可以由序列和散列的方式来决定。