.NetGurus

Diğer Yazılar

Google a Ekle

Add to Google

Asp.Net' te ViewState Sıkıştırması

İstemcilerin, sayfalarımızı mümkün olduğunca kısa bir süre de görüntüleyebilmesi öncelikli hedeflerimizdendir. Bu performans bir çok etkene bağlıdır. Örneğin, veritabanı işlemlerimizin hızı, sayfadaki hesaplama vb işlemlerin hızı, sayfa aktarımının sıkıştırılması vs vs. Daha önce sayfa içeriğinin sıkıştırılması ile ilgili HTTP Sıkıştırması (HTTP Compression) konulu bir yazı yazmıştım. HTTP Sıkıştırması konulu bu yazıyı okumanızı şiddetle tavsiye ediyorum.

Bu yazımda ise performans konusunda yine önemli kazançlar sağlamanızı sağlayabilecek bir konudan yani ViewState sıkıştırmasından bahsetmeye çalışacağım.

Bildiğiniz üzere web sayfalarımızdaki sınıflarımız, alanlarımız, değişkenlerimiz vs vs kontrollerdeki değerler de dahil olmaz üzere sayfanın her gidiş gelişinde(postback) kaybolur. Zaten aksi durumda, binlerce kullanıcısı olan bir web uygulamasında-sitesinde- gerekecek bellek ve işlemciye sahip sunucuyu yer yüzünde bulmak mümkün olmazdı herhalde. Ancak sayfalardaki değerlerin her postbackte kaybolması web programcılığını imkansız bir hale getirirdi. Ya da bu değerleri tamamen kaybetmesek de her seferinde post edilen formun içinden tek tek alıp ilgili kontrollere geri yüklememiz gerekse bu da işimizi çok zorlaştırırdı. Çünkü gerçekte sizin sayfanın kod kısmında kullandığınız bir textbox ile ziyaretçinin sayfada gördüğü textbox aynı şeyler değildir. Kodda kullandığımız textbox metodları eventleri olan bir kontroldür ancak istemcide görünün textbox ise basit bir html yazısıdır. Ziyaretçinin sayfayı post etmesi, sayfadaki form elemanlarının ikili değerler halinde ("textBoxKullanıcıAdi", "Ömer Faruk") ... şeklinde gönderilmesi şeklindedir. İşte bu aşamada bu verinin kullanılarak kod tarafındaki textBoxKullanıcıAdi kontrolüne bu değerin atanması ile işimiz kolaylaşmış olur.

Asp.Net' te bu mekanizma ViewState ile sağlanır. Sayfadaki kontrollerde bulunan değerler ya da daha sonra kullanmak üzere sizin ViewState' e attığınız bilgiler özel şekilde bir metin haline dönülştürülerek sayfanın içinde gizli bir alanda saklanır. Bu işlem sayfanın SavePageStateToPersistenceMedium metodunda yapılır. ViewState değerini sayfada göremezsiniz ama sayfanın kaynağına yani html sine bakarsanız görebilirsiniz, insanın okuyamayacağı saçma sapan görünen ama uzun mu uzun bir yazı şeklindedir. Ziyaretçi sayfada metin girme seçenek seçme vb işlemler yapıp da düğmeye basarak vb bir şekilde sayfayı tekrar post ettiğinde sayfanın LoadPageStateFromPersistenceMedium metodunda ViewState' deki değerler ilgili kontrollere geri yüklenir elbette aralarından değişenler olmuşsa yeni değerler kullanılır.

ViewState bilgisi illa ki sayfanın html sinde saklanmak zorunda değildir. SessionState, veritabanı vb. yerlerde de saklanabilir. Ancak web ortamında kullanıcının sayfanızı kapattığı ya da terkettiğini bilememeniz sebebi ile ilgili ViewState bilgisini ne zamana kadar saklamanız gerektiğini bilemezsiniz. Bunu bilseniz bile ziyaretçi sayınız da çok ise bu kadar veriyi saklayacak kaynaklara sahip olamayabilirsiniz. Bu sebeple genel olarak ViewState' in sayfanın içerisinde yani bir daha lazım olana kadar istemci makinede saklanması doğru bir tercihtir.

Biraz karışık da olsa işin özünü anlatmaya çalıştıktan sonra şimdi gelelim konumuza. ViewSate' in sayfanın içinde istemciye gönderilmesinin yukarıda anlatılan avantajlarının yanında sayfanın aktarımını ve dolayısı ile de yüklenmesini geciktireceği bariz bir dezavantajdır. Bu bilginin istemci tarafında hiç kullanılmayacağını da göz önüne alırsak bu düz yazı şeklindeki bilgiyi sıkıştırmamız için hiç bir engel yok denebilir. Tabi sıkıştırma işleminin sunucunun işlemci kaynaklarını kullanacağını düşünürsek içinde bulunduğumuz duruma göre aktarım hızı yerine işlemci hızını da tercih etmemiz gerekebilir. Sunucumuzun işlemcisinin boş kapasitesinin olduğunu yani işlemcinin sorun oluşturmadığını varsayarak konumuza devam edelim.

Daha önce de belirttiğim gibi ViewState' in kaydedilmesi ve yüklenmesi sırasıyla sayfanın SavePageStateToPersistenceMedium ve LoadPageStateFromPersistenceMedium metodları içinde olur. İşte biz de bu metodları override ederek ve framework içindeki sıkıştırma araçlarını kullanarak ViewState bilgisini sıkıştıracağız. Bunun için aşağıda göreceğiniz şekilde Page(Sayfa)' dan türeyen bir class ile bu metodları override edeceğiz. Bundan sonra yapmanız geerken tek şey web sayfalarınızı System.Web.UI.Page de bu class' tan yani PageWithCompressedViewstate ten türetmenizdir.

Yazıyı daha fazla uzatmamak için kodu açıklamıyorum. İşte kodumuz:

Imports System.IO

Imports System.IO.Compression

Public Class PageWithCompressedViewstate : Inherits System.Web.UI.Page

     Private Const buffer_size As Integer = 1000

     Public Shared Function ReadAllBytesFromStream(ByVal stream As Stream) As Byte()

           Dim readBytes() As Byte = New Byte(0) {}

           Dim offset As Integer = 0

           While True

                Array.Resize(readBytes, readBytes.Length + buffer_size)

                Dim bytesRead As Integer = stream.Read(readBytes, offset, buffer_size)

                Array.Resize(readBytes, readBytes.Length - buffer_size + bytesRead)

                If bytesRead = 0 Then

                      Exit While

                End If

                offset += bytesRead

          End While

          Return readBytes

     End Function

 

     Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object

          Dim vState As String = Me.Request.Form("__VSTATE")

          Dim compressedbytes As Byte() = System.Convert.FromBase64String(vState)

          Dim ms As New MemoryStream(compressedbytes)

          Dim gz As New GZipStream(ms, CompressionMode.Decompress)

          Dim bytes() As Byte = ReadAllBytesFromStream(gz)

          gz.Close()

          ms.Close()

          Dim format As New LosFormatter

          Return format.Deserialize(System.Convert.ToBase64String(bytes))

      End Function

      Protected Overrides Sub SavePageStateToPersistenceMedium(ByVal viewState As Object)

           Dim format As New LosFormatter

           Dim writer As New StringWriter

           format.Serialize(writer, viewState)

           Dim viewStateStr As String = writer.ToString()

           Dim bytes As Byte() = System.Convert.FromBase64String(viewStateStr)

           Dim ms As New MemoryStream()

           Dim compressedzipStream As New GZipStream(ms, CompressionMode.Compress, True)

           compressedzipStream.Write(bytes, 0, bytes.Length)

           compressedzipStream.Close()

          Dim compressedBytes() As Byte = ms.ToArray

           ms.Close()

          Dim vStateStr As String = System.Convert.ToBase64String(compressedBytes)

          If String.IsNullOrEmpty(Request("HTTP_X_MICROSOFTAJAX")) = False Then

                ScriptManager.RegisterHiddenField(Me, "__VSTATE", vStateStr)

          Else

                 ClientScript.RegisterHiddenField("__VSTATE", vStateStr)

          End If

     End Sub

End Class

Sonuç: Bu işlemi denemek için bir gridview içinde veritabanından getirilmiş verileri gösteren bir sayfa hazırladım. Sayfa normal bir şeklide oluşturulup da istemciye yüklendiğinde dosya boyutu 313KB oldu. Aynı sayfayı ViewState bilgisini sıkıştırarak oluşturduğumuz da ise boyutu 233KB' a düştü. Yani yaklaşık olarak %25' lik bir kazanç sağlamış olduk. Tabi bu oran her sayfanın içeriğine göre değişecektir ama performans performanstır.

Bu yazıyı ilk değerlendiren siz olun

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by yavuz on 12 Kasım 2008 Çarşamba 02:15
Permalink | Yorumlar (0) | Post RSSRSS comment feed