项目里数据库表有很多字段,而且有不少字段不确定长度,所以决定,把大多数不常用字段用 XML 序列化的方式,保存到一个字段内,不过却发现,从网上取一条 10K 左右的 XML 数据,反序列化,解析、转义,然后分别设置到4、5个对象中,这些对象,再对自身的不常用字段进行 XML 序列化,然后保存对象到数据库,竟然要花 5 秒左右的时间。
下载了一个 DotTrace + TestDriven.Net,用它对单元测试进行了分析,发现,这 5 秒左右的时间,有 4 秒多都花在了 XML 序列化上,那么解决问题的方法就比较明确,改用另外的序列化方法。
因为项目使用了 Coolite,Json 就成了一个比较简单的选择,于是用 Coolite 自带的 Json 序列化(其实是 Newtonsoft Json)进行序列化测试,对于我测试的 7K 左右的大多数是字符串的数据来说,Json 的速度大概是 XML 的 3 倍左右,而且序列化出的字符串,也比 XML 小三分之一左右。于是把数据库中的序列化字段改成 Json,速度马上有了一个大的提高。
不过,在网上搜到了一篇文章,比较了几种序列化方式,说是 PHP-RPC 是综合效果最好的,于是也找来,一并写了测试程序如下:
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
static readonly Stopwatch Stopwatch = new Stopwatch();
static string _temp = "" ;
static void Main()
{
var xmlStr = ResourceHelper.ReadToEnd( typeof (Program), " test.xml " );
var trade = SingleTrade.FromXml(xmlStr);
CheckTwoWayTime( " XML " , () => _temp = trade.ToXml(), () => SingleTrade.FromXml(_temp));
CheckTwoWayTime( " JSON " , () => _temp = JSON.Serialize(trade), () => JSON.Deserialize < SingleTrade > (_temp));
CheckTwoWayTime( " PHP " , () => _temp = PhpSerialize(trade), () => PhpDeserialize(_temp));
}
private static void CheckTwoWayTime( string text, CallbackVoidHandler sCallback, CallbackVoidHandler dCallback)
{
var s = CheckTime(sCallback);
var d = CheckTime(dCallback);
Console.WriteLine( " {0} Serialize MS: {1}, Deserialize MS: {2}, Length of string: {3} " , text, s, d, _temp.Length);
}
private static long CheckTime(CallbackVoidHandler callback)
{
Stopwatch.Reset();
Stopwatch.Start();
callback();
var ms = Stopwatch.ElapsedMilliseconds;
return ms;
}
private static string PhpSerialize(SingleTrade obj)
{
var php = new org.phprpc.util.PHPFormatter();
var m = new System.IO.MemoryStream();
php.Serialize(m, obj);
var result = Convert.ToBase64String(m.ToArray());
return result;
}
private static SingleTrade PhpDeserialize( string s)
{
var php = new org.phprpc.util.PHPFormatter();
var m = new System.IO.MemoryStream(Convert.FromBase64String(s)) {Position = 0 };
var result = (SingleTrade)php.Deserialize(m);
return result;
}
}
运行了三次这个程序,三次的结果如下:
C:\Debug>Besten.Migration.exe
XML Serialize MS: 148, Deserialize MS: 161, Length of string: 7233
JSON Serialize MS: 82, Deserialize MS: 29, Length of string: 5344
PHP Serialize MS: 8, Deserialize MS: 18, Length of string: 8836
C:\Debug>Besten.Migration.exe
XML Serialize MS: 161, Deserialize MS: 165, Length of string: 7233
JSON Serialize MS: 74, Deserialize MS: 42, Length of string: 5344
PHP Serialize MS: 13, Deserialize MS: 17, Length of string: 8836
C:\Debug>Besten.Migration.exe
XML Serialize MS: 165, Deserialize MS: 180, Length of string: 7233
JSON Serialize MS: 67, Deserialize MS: 24, Length of string: 5344
PHP Serialize MS: 9, Deserialize MS: 26, Length of string: 8836
可以看到,PHP-RPC 序列化的速度,大概是 XML 的 10 到 20 倍之间,反序列化的速度也是 XML 的 8 倍左右,所以,项目下一步的计划就是把序列化字段的方法改成 PHP-RPC 了。
看了一下 PHP-RPC 的序列化方法描述,它的字符串序列化比较特殊,使用前置长度而不进行转义的方式,所以速度比较快、而占用内存比较小也就不奇怪了。只是还没研究它序列化出的字节数组究竟是否直接就是字符串,而不需要用 Base64 呢?