zoukankan      html  css  js  c++  java
  • asp.net 2.0中通过压缩ViewState改善性能

    原文地址:http://www.dotnetbips.com/articles/22d33d11-1a75-42c8-bbf6-ca1a345d3fcf.aspx
    [原文源码下载]


    [翻译]asp.net 2.0中通过压缩ViewState改善性能


    原文发布日期:2007.03.08
    作者:Bipin Joshi
    翻译:webabcd


    介绍
    开发人员经常担心他们web站点的性能。每一个开发者都想他们的web站点的性能是最优化的。影响你web站点性能的有很多因素,ViewState就是其中之一。本文我将给大家提供一个通过压缩ViewState来改善性能的方法。


    什么是ViewState
    虽然本文并不是专门来研究ViewState的,但我们还是简单的讨论一下吧。你如果看过web form生成的HTML代码的话,就会发现在一个名为__VIEWSTATE的隐藏域。聪明的ASP.NET会持久化这些控件的值到这个隐藏域中,这对于往返服务器的过程中保存控件的值是非常有用的。但是,此时ViewState会带来性能问题。因为ViewState要在服务端与客户端之间传输,所以会增加网络带宽的流量。

    要减少ViewState的话,可以关闭ViewState,就是设置控件的EnableViewState属性,如果设置该属性为false则控件的ViewState将被关闭。但是,如果没有ViewState的话,控件状态持久化的工作就需要你自己来做了,这将是令人非常头痛的。还有另一种减少ViewState的方法就是本文将要介绍的方法,即在ViewState传输之前先压缩它,这样ViewState的数据将会大幅度减少。

    在ASP.NET 1.x中如果我们要使用压缩功能的话需要自己写一些代码。而现在.NET 2.0提供了System.IO.Compression命名空间,将会使压缩功能的实现变得非常简单。System.IO.Compression命名空间的GZipStream类可以处理流的压缩和解压,注意,GZipStream只能以流的方式工作。GZipStream类不知专门压缩ViewState而设计的,所以我们为了实现ViewState的压缩和解压要自己写一些代码。


    开发ViewStateHelper
    我们首先用Visual Studio新建一个web站点,然后再App_Code文件夹中增加一个名为ViewStateHelper的类。类文件顶部要引入的命名空间如下
    using System.IO;
    using System.IO.Compression;

    System.IO命名空间为我们提供了流的类,如MemoryStream。The System.IO.Compression命名空间为我们提供GZipStream类,它允许你呈现gzip格式的数据(RFC 1952)。


    压缩数据
    现在增加一个名为Compress()的方法如下
    public static byte[] Compress(byte[] data)
    {
        MemoryStream ms 
    = new MemoryStream();
        GZipStream stream 
    = new GZipStream(ms, CompressionMode.Compress);
        stream.Write(data, 
    0, data.Length);
        stream.Close();
        
    return ms.ToArray();
    }

    这个Compress()静态方法接收一个字节数组类型的变量并压缩它,返回的是一个压缩后的字节数组。它首先实例话一个MemoryStream类,它用来呈现内存中的流。然后通过MemoryStream和压缩模式两个参数创建一个GZipStream对象。你可以用任何流类型来替换MemoryStream。被压缩的数据将写进这个流。GZipStream类的Write()方法会接收一个字节数组类型的变量,然后压缩它并写进流中(在我们的例子中是MEmoryStream)。写完之后GZipStream被关闭。最后,MemoryStream的ToArray()方法将转换流数据到字节数组中。


    解压数据
    为了解压数据,我们要增加另一个名为Decompress()的方法,其关键代码如下
    public static byte[] Decompress(byte[] data)
    {
        MemoryStream ms 
    = new MemoryStream();
        ms.Write(data, 
    0, data.Length);
        ms.Position 
    = 0;
        GZipStream stream 
    = new GZipStream(ms, CompressionMode.Decompress);
        MemoryStream temp 
    = new MemoryStream();
        
    byte[] buffer = new byte[1024];
        
    while (true)
        
    {
            
    int read = stream.Read(buffer, 0, buffer.Length);
            
    if (read <= 0)
            
    {
                
    break;
            }

            
    else
            
    {
                temp.Write(buffer, 
    0, buffer.Length);
            }

        }

        stream.Close();
        
    return temp.ToArray();
    }

    这个Decompress()静态方法接收一个已压缩的字节数组,返回一个解压后的字节数组。首先,它创建了一个MemoryStream对象,并将一个已压缩的字节数组写进去。然后这个流将作为参数提供给GZipStream的构造函数,注意此时的压缩模式为Decompress。解压后的数据也需要在某个地方保存,所以接下来创建的另一个MemoryStream对象就是作此用途。接着我们用一个while循环从GZipStream读取出解压后的数据,每一块都是1024字节。然后这个数据就被写进MemoryStream了。最后,GZipStream被关闭,解压后的内容作为一个字节数组被返回。


    新建一个web form
    现在打开一个web form,拖拽一个SqlDataSource控件到上面,配置它以使其可以从Northwind数据库中读取Customers表的记录。


    拖拽一个GridView控件并设置它的DataSourceID属性为你刚才配置好的SqlDataSource控件的ID。确保运行这个web form是我们想要的结果,示例如下



    定制ViewState的序列化和反序列化
    你不用关心ViewState的序列化和反序列化,因为这些都是自动的。但是因为咱们需要压缩ViewState,所以需要定制它的序列化和反序列化。Page基类有两个虚拟方法,SavePageStateToPersistenceMedium()和LoadPageStateFromPersistenceMedium()。它们分别允许你定制ViewState的序列化和反序列化。

    我们首先在web form的后置代码中重写SavePageStateToPersistenceMedium()方法。在这个方法中,你将压缩ViewState并存储它到隐藏域中。代码如下
    protected override void SavePageStateToPersistenceMedium(object state)
    {
        LosFormatter formatter 
    = new LosFormatter();
        StringWriter writer 
    = new StringWriter();
        formatter.Serialize(writer, state);
        
    string viewState = writer.ToString();
        
    byte[] data = Convert.FromBase64String(viewState);
        
    byte[] compressedData = ViewStateHelper.Compress(data);
        
    string str = Convert.ToBase64String(compressedData);
        ClientScript.RegisterHiddenField(
    "__MYVIEWSTATE", str);
    }

    SavePageStateToPersistenceMedium()方法接收一个ViewState对象。在该方法中创建一个LosFormatter对象,LosFormatter类允许你序列化和反序列化ViewState中的数据。LosFormatter类的Serialize()方法接收两个参数,分别是一个流和一个对象,结果是把这个对象序列化到这个流中。在我们的例子里,ViewState被序列化到了StringWriter里。StringWriter的ToString()方法返回一个字符串用于呈现ViewState数据。这个字符串是Base64格式的(在ASP.NET中就是这么存储到ViewState中的),我们需要把它转换成我们想要的格式。Convert类的FromBase64String()方法就可以做这个工作。FromBase64String()方法返回一个字节数组数据,然后使用我们的ViewStateHelper类的Compress()方法压缩它。然后使用Convert类的ToBase64String()方法把被压缩的数据转换成Base64格式。最后,我们用ClientScript的RegisterHiddenField()方法把这个已压缩的Base64格式的数据注册到一个名为__MYVIEWSTATE的隐藏域中。

    这就是我们压缩ViewState的方法。另外还有一个同等重要的工作就是解压,我们通过重写LoadPageStateFromPersistenceMedium()方法来实现这样的功能,其代码如下
    protected override object LoadPageStateFromPersistenceMedium()
    {
        
    string viewstate = Request.Form["__MYVIEWSTATE"];
        
    byte[] data = Convert.FromBase64String(viewstate);
        
    byte[] uncompressedData = 
        ViewStateHelper.Decompress(data);
        
    string str = Convert.ToBase64String(uncompressedData);
        LosFormatter formatter 
    = new LosFormatter();
        
    return formatter.Deserialize(str);
    }

    这个方法首先读出__MYVIEWSTATE隐藏域的值,该值为Base64格式的被压缩ViewState。为了解压它,你的第一步工作仍然是把它转换为一个字节数组,我们通过Convert类的FromBase64String()方法来做。接下来我们用ViewStateHelper类的Decompress()方法解压数据。然后用Convert类的ToBase64String()方法再一次把解压后的数据转换为Base64格式的字符串。最后,LosFormatter对象反序列化解压后的ViewState

    以上就是压缩和解压ViewState的全部内容。经过我对本例的实际测试发现未经压缩的ViewState大小为13,568字节,压缩后的ViewState大小为5,932字节。这对于改善性能是非常有用的,你说呢?


    总结
    从本文中你学到了如何通过压缩ViewState来改善你web站点的性能。GZipStream类提供了现成的把你的数据压缩成gzip格式的方法。被压缩的数据需要通过重写Page基类的SavePageStateToPersistenceMedium()方法保存。相似的,读取ViewState后我们需要通过重写LoadPageStateFromPersistenceMedium()来解压数据。
  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/hdjjun/p/1603162.html
Copyright © 2011-2022 走看看