在silverlight forum看了一个关于如果提高wcf性能的贴,觉得很受用。显然对于分布式应用程序,似乎没有什么比提高客户端的响应速度更值得关切。之后查找了相关资料,并动手做了一些练习.当然我也看到了黎波的那个关于提升web service性能实战的pdf.
1.datasetsurrogate加速webservice: 关于datasetsurrogate我查过msdn,显示这个类所在的命名空间Microsoft.Synchronization.Data,不过在.net framework 3.5sp1该命名空间写已经没有该类.ms在.net 1.1出的这个datasetsurrogate类,似乎已经被抛弃.不过在ms网站依旧可以下载得到datasetsurrogate 代码,需要自己编译生成dll。
2.在使用web service时候,常常习惯返回dataset。不过对于dataset有一个RemotingFormat属性,可以设置为serializationFormat.Xml和serializationFormat.Binary关于2者的区别在于序列化的深度,我的理解是xml格式早晨冗余,binary格式传输效率好,但是会把数据体积变得更庞大,这样反倒影响了性能,但是转化为binary可以对数据加密传输.因此要利用binary本身的传输优势,压缩显得非常重要.下面是测试结果
getCompressBytes:读取数据到dataset,用二进制序列化后,采用gzip压缩,返回
getDataSetBytes:读取数据到dataset,用二进制序列化(不是设置RemotingFormat属性值),返回
getDataSetBytes:读取数据到dataset,返回
从上面看似乎结果并不是上面所说的那样,我的解释是由于测试时间是从调用getComPressBytes开始到结束,中间的时间包括用二进制序列化,以及压缩的过程,而我关心的只是传输的过程,压缩应该说是一个耗时的过程.
3.SharpZipLib
gzip压缩是.net System.Io命名空间下的一个压缩算法.不过我更关心SharpZipLib开源的压缩框架,支持Zip,Gzip,Tar,bZip2.多余的不说下面看看SharpZipLib 和gzip的压缩率以及整个过程的时间:
getComPressBytes:compress legth:751893,time:00:00:02:1001201(.net自带的gzip) 压缩率22%
SharpZipLib:CompressBytes:583020 unCompress bytes:3339243 time:00:00:00:6660381(采用最高压缩率的方式)17%
显然对于同一个dataset中的2w条数据转化为binary格式的大小是一样的,压缩率差距不太大,但是传输时间几乎为3倍。显然上面的结果只对于文本类型,对于pdf格式的文件压缩并不明显,对于rar,zip文件就几乎不能被压缩,因为无论哪种压缩方式归根结第都是基于哈夫曼算法。(当然这种说法不是很严格。下面贴几段代码
[WebMethod(Description = "3.将dataset对象用Binary序列,并用Compress(iis自带的压缩)压缩后返回")]
public byte[] getCompressBytes()
{
DataSet ds = getTestData();
//byte[] buffer = getTestData(fileName);
/*----*/
BinaryFormatter fmater = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
fmater.Serialize(ms, ds);
/*----*/
byte[] buffer = ms.ToArray();
return DataFormatter.GetBinaryFormatDataCompress(buffer);
}
public static byte[] GetBinaryFormatDataCompress(byte[] binaryDataResult)
{
return Compress(binaryDataResult);
}
/// <summary>
/// 压缩数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static byte[] Compress(byte[] data)
{
byte[] bData;
MemoryStream ms = new MemoryStream();
GZipStream stream = new GZipStream(ms, CompressionMode.Compress, true);
stream.Write(data, 0, data.Length);
stream.Close();
stream.Dispose();
//必须把stream流关闭才能返回ms流数据,不然数据会不完整
//并且解压缩方法stream.Read(buffer, 0, buffer.Length)时会返回0
bData = ms.ToArray();
ms.Close();
ms.Dispose();
return bData;
}
SharpZipLib压缩:
[WebMethod(Description = "4.将list对象用Binary序列,并用ICSharpCode.SharpZipLib压缩后返回")]
public byte[] getDataListSharpZipComPressBytes()
{
// byte[] buffer = getTestData(fileName);
IList<Users> list = getTestDataList();
/*----*/
BinaryFormatter ser = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
ser.Serialize(ms, list);
byte[] buffer = ms.ToArray();
/*----*/
byte[] zipbuffer = new CompressionHelper(CompressionLevel.BestSpeed).CompressToBytes(buffer);
//ms.ToArray();
return zipbuffer;
}
public byte[] CompressToBytes(byte[] bytesToCompress)
{
MemoryStream ms = new MemoryStream();
Stream s = GetOutputStream(ms);
s.Write(bytesToCompress, 0, bytesToCompress.Length);
s.Close();
return ms.ToArray();
}
当然啊在实际应用中,我们将数据压缩之后,通常在客户端还需要进行解压缩,反序列化而且很多时候传输的不是dataset,而是list<T>或单个对象,或一些值类型。
buffer = client5.getDataListSharpZipComPressBytes();//通过wcf获取压缩后的list
buffer = new CompressionHelper(CompressionLevel.BestCompression).DecompressToBytes(buffer);//解压缩
IList<webServiceTest.Users> list = DataFormatter.RetrieveDataList(buffer) as IList<webServiceTest.Users>;//转化为实际要用的list<Users>
我和一个资深的同事聊起关于wcf数据压缩的话题,他提出了一个问题,就是在实际应用中,对于压缩blob(大数据)就值得考虑,其实是一个非常耗cpu资源的事情,而且还不支持多核优化,就是说不管你服务器是几核,实际使用的是仍然是单核,因此对于服务器的内存,还是cpu都是极大的考验。不过对于数据压缩耗cpu资源这个很容易体会,我读取一个175m的pdf文件用SharpZipLib1压缩(zip)cpu,,内存使用率暴涨,这和直接用winrar效果一样,不过对于cpu倒不是如同事说的单核运行。