SharpZipLib 数据压缩

在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本身的传输优势,压缩显得非常重要.下面是测试结果

未命名 这个测试时从数据库读取2w条数据,分别采取下列措施:

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倒不是如同事说的单核运行。

你可能感兴趣的:(zip)