场景是这样的,有个逻辑对象的结构如下:
struct Msg
{
int type;
char name[12];
float height;
float width;
int count;
int flag;
}
C++和C#分别来做这个对象的传输。
传输方面没什么好说的,是操作系统IO的事情,和语言无关。
下面是收到数据之后进行parse,为了对比,我们把数据parse一百万次。
C++从socket收到char* input_raw_buf之后,只要:
Msg* msg;
memcpy(msg, input_raw_buf, sizeof(Msg));
一百万次耗时20毫秒。
C#从socket收到byte[] input_raw_buf之后,需要做:
Convert.ToInt32()
Convert.ToString()
这种方式被批太落后,直接就没测试。
C#优化,改用Marshal:
一百万次耗时1781毫秒。比C++慢80多倍。据说和上面被批最原始的方式性能相当。有谣言说Marshal只是语法糖。
C#再优化,改用BinaryReader:
BinaryReader reader;
msg.type = reader.ReadInt32();
还不够快。
再优化,改用伪指针的方式:
fixed (byte* p = data)
msg.type = *(int*)p;
msg.name = new string((sbyte*)p, 4, 12)
一百万次耗时484毫秒。比C++慢20多倍。
无法可想,没法再优化了。
最终的结果是,在parse二进制格式的数据的时候,C#比C++最少要慢20多倍。
(建议各位,不要采用unsafe的方式构建C#程序)
当然,我们也不会整天去parse二进制数据,因此C#众不用太担心。
我也用C#写过不少程序,性能也都马马虎虎能接受。
不过,一定要注意,C#在某些特定的环境下,有可能会慢得出乎你的意料。
(Java众先不要高兴,Java必定有同样的问题,因为Java和C#的基础架构是一样的)