ViewState, ASP.NET uygulamalarında, sayfanın kendi üzerinde
veri taşımasına olanak sağlayan bir yapıdır. Bu veriler, HTML kodlar içerisinde
saklı alanlara (hidden field) gömülerek, istemci-sunucu arasında taşınırlar. Bu
yüzden, eğer büyük ölçekli bir GridView ya da çok fazla eleman içeren
DropDownList’ler gibi, ViewState’i şişirecek kontroller kullanılırsa, ciddi bir
performans kaybı yaşanabilir. Böyle bir performans kaybı yaşamamak için,
uygulama geliştiricisinin bir takım iyileştirmeler yapması gerekir.
Yapılabilecek iyileştirmelerden biri de ViewState’in boyutunu azaltmak üzere
sıkıştırma algoritmalarından faydalanmaktır.
D e f l a t e = dflt
Sayfamızın ViewState’i
içeriside a,b,c verileri olduğunu kabul edelim. Eğer biz bu verilerin sayısını
3’ten 2’ye düşüremiyorsak, toplam veri boyutunu azaltmanın tek yolu a,b,c
verilerinin boyutlarını, verileri değiştirmeden azaltmak, diğer bir deyişle
ilgili veri kümesini sıkıştırmaktır. Veriyi sıkıştırmak için çeşitli
algoritmalardan faydalanılabilir. Bu algoritmalardan bir tanesi olan Deflate’i,
.Net 2.0 ile birlikte gelen ve System.IO.Compression isim alanı altında bulunan
tipler aracılığıyla, uygulamalarımızda kullanabiliriz.
System.IO.Compression |
DeflateStream
|
: Stream’leri sıkıştırmak ya
da açmak için gerekli üyeleri barındırır.Deflate algoritmasını kullanır.Bu
algoritma 4GB altındak her veriye uygulanabilir;ancak daha önceden
sıkıştırılmış veri kümesi üzerinde deflate
algoritmasını çalıştırmak, boyutu azaltmak yerine arttırabilir. |
GZipStream |
: DeflateStream’den tek
farkı,sıkıştırılmış kümeye header bilgisi ilave ederek,GZip
formatına destek vermesidir.Arka tarafta kulanılan algoritmalar aynı olduğu
için, bu şekilde bir formatlamaya gerek yoksa performans açısından
DeflateStream tercih edilmelidir. |
CompressionMode |
: Bir
numarlandırıcıdır.Sıkıştırmak (Compress) ve sıkıştırılanı açmak (Decompress)
şeklinde iki değer içerir. |
|
.Net 2.0 ile gelen DeflateStream
ve GzipStream tipleri, System.IO.Compression isim alanı altında
bulunmaktadırlar. |
Şimdi, isterseniz, bu
bahsettiklerimizi bir uygulama üzerinde test edelim. Öncelikle yeni bir web
projesi oluşturup, default.aspx sayfamıza bir adet GridView kontrolü atalım.
<asp:GridView
ID="grdProducts" runat="server" /> |
Daha sonra kod tarafına geçip, GridView
kontrolümüze, AdventureWorks’ün Production.Product tablosunu bağlayalım ve sayfayı bu haliyle çalıştırıp, kaynağına bakalım.
default.aspx.cs |
protected void Page_Load(object sender,
EventArgs e)
{
string _connString="data
source=localhost;database=AdventureWorks;integrated security=SSPI";
using (SqlConnection _conn = new SqlConnection(_connString))
{
string _query = "SELECT * FROM
Production.Product";
SqlDataAdapter _da=new
SqlDataAdapter(_query,_conn);
DataTable _dt = new DataTable("Products");
_da.Fill(_dt);
grdProducts.DataSource = _dt;
grdProducts.DataBind();
}
} |
Yukarıda, - ufak! - bir bölümünü gördüğümüz ViewState’in boyutu 340076 byte
olmakla birlikte, bir de tüm bu HTML kodların, sunucu-istemci arasında taşınıyor
olması, ciddi bir problemin göstergesidir. Dolayısıyla bu denli bir ViewState’in
de asla optimize edilmeden kullanılmaması gerekir.
Bu ViewState’i ziplesek de mi saklasak, ziplemesek de mi saklasak?
Getireceğimiz çözüm aslında
WinZip,WinRar gibi programların çalışma mantıklarından farklı değildir.
Örneğimizde, içerisinde Compress() ve Decompress() metodlarını barındıran bir
sınıfa ihtiyamıcız olacaktır. Öyleyse bu metodları aşağıdaki gibi oluşturalım.
ZipState.cs |
public static byte[]
Compress(byte[] data)
{
MemoryStream ms = new MemoryStream();
DeflateStream stream = new DeflateStream(ms, CompressionMode.Compress);
stream.Write(data, 0, data.Length);
stream.Close();
return ms.ToArray();
}public static byte[]
Decompress(byte[] data)
{
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
DeflateStream stream = new DeflateStream(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();
}
|
Her iki metod da
parametre olarak bir byte dizisi alıp,geriye yine bir byte dizisi döndürken,
DeflateStream tipinden örneklediğimiz nesneyle sıkıştırma-açma
işlemini gerçekleştirmektedirler (Kodun nasıl işlediği üzerinde uzun uzun
durmayacağım, bu kısmı siz değerli okurlara bırakıyorum).
Sınıfımız hazır olduğuna
göre, geriye, sayfamızın SavePageStateToPersistenceMedium() ve
LoadPageStateFromPersistenceMedium() metodlarını ezerek, ViewState’i "bizim istediğimiz şekilde" oluşturmak kalıyor.
default.aspx.cs |
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 = ZipState.Compress(data);
string str = Convert.ToBase64String(compressedData);
ClientScript.RegisterHiddenField("__CompressedVIEWSTATE", str);
}
protected override object LoadPageStateFromPersistenceMedium()
{
string viewstate = Request.Form["__CompressedVIEWSTATE"];
byte[] data = Convert.FromBase64String(viewstate);
byte[] uncompressedData = ZipState.Decompress(data);
string str = Convert.ToBase64String(uncompressedData);
LosFormatter formatter = new LosFormatter();
return formatter.Deserialize(str);
} |
Çözümü test ettiğimizde,
daha önce 340076 byte olan ViewState’in, sıkıştırma sonrası
49204 byte’a düştüğünü
görürürüz.Bu da %85 gibi bir sıkıştırma oranı anlamına gelmektedir.
Dikkat!
Bu noktada Deflate algoritmasının her koşulda aynı
sonucu üretmediğinin altını çizmek gerekir (Çizdim bile:)).Hatta algoritma
düzgün çalışmaz ve veri sıkıştırılamazsa, Compress() metodunun döndürdüğü
verinin boyutu, eklenen header’larla birlikte, orjinal boyutun da üstüne
çıkabilir.Örneğin, projemize eklediğimiz ve boş olan default2.aspx sayfası, ViewState’inde
52 byte veri tutarken,Deflate algoritmasını
kullandığımızda, boyut 164 byte’a
yükselmektedir.
default2.aspx - Sıkıştırılmadan önce ViewState |
<input type="hidden"
name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwUJNzgzNDMwNTMzZGQkufqAWsUnKW76l4cm6MlUAAAAAA==" /> |
default2.aspx - Sıkıştırma işleminden sonra ViewState |
<input type="hidden"
name="__CompressedVIEWSTATE" id="__CompressedVIEWSTATE"
value="7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJni
GAqsgfP358Hz8i/u9f8zed/aa/7o89OLi3f2/n/r17s/8H"
/> |
|
Deflate algoritması, her koşulda
aynı sonucu üretmeyebilir.Bu yüzden, verinin orjinal boyutunun aşılıp
aşılmadığının kontrol edilmesi gerekir. |
Peki ya yükleme süreleri?
ViewState’i sıkıştırmak, sunucu için ekstra iş demektir. Dolayısıyla, test
sonuçlarının daha sağlıklı bir hal alabilmesi için, yaptığımız işlemlerin
sunucuda yansımalarını da izlemek gerekir. Bu amaçla Trace özelliğinden
faydalanılabilir.
default.aspx - Sıkıştırma yok
default.aspx - Sıkıştırma var
|
Trace özelliğini kullanmak için,
sayfanın @Page direktifinde, Trace="true" olduğunu söylemek gerekir. |
Sonuç olarak
ViewState’i sıkıştırırken kullandığımız algoritma, sonucu belirleyecektir.
Deflate algoritması bu anlamda başarılı bir algoritma olsa da her zaman aynı
sonucu üretmeyebilir. Dolayısıyla optimizasyon yaparken göz çıkarmamak
gerekeceğinden, sayfanın yayınlanmadan önce, sıkıştırmanın ne ölçüde başarılı
olduğu mutlaka test edilmeli, sunucuda meydana gelen gecikme süreleri
izlenmedilir.
Tabi ki, ViewState ile ilgili yapılabilecek optimizasyonlar
yalnızca "sıkıştırma işlemi" ile sınırlı değildir. Sıkıştırmanın yanında,
ViewState’in session içerisinde ya da SQL’de saklanması gibi konular da vardır (http://www.csharpnedir.com/makalegoster.asp?MId=233). Biz bu makalemizde, yalnızca, sıkıştırma
algoritmalarından nasıl faydalanabileceğimizi inceledik. Bir dahaki makalede
görüşmek üzere,hoşçakalın...
Kaynaklar:http://www.codeproject.com/aspnet/ViewStateCompression.asp
Cenk Özdemir
[email protected]
Makale:
ViewState İçeriğini Sıkıştırmak ASP.NET Cenk Özdemir
|