0

فشرده سازی ViewState

 
amirpetrucci0261
amirpetrucci0261
کاربر طلایی1
تاریخ عضویت : تیر 1388 
تعداد پست ها : 27726
محل سکونت : http://zoomstar.ir/

فشرده سازی ViewState
چهارشنبه 10 آذر 1389  5:09 AM

مدتی پیش در حال توسعه برنامه ای بودم که یک صفحه Asp.net حجیم داشت. این صفحه دارای 30 کنترل مختلف بود. همانطور که میدانید در چنین شرایطی بسیار مفید است اگر Viewstate را برای کنترلهایی که در واقع به آنها نیاز نداریم غیرفعال نماییم، مثلا برای literal ها یا Label ها.
پس از انجام این کار من متوجه شدم که ViewState مورد نظر همچنان حجم بالایی دارد و در نتیجه هنوز هم مشکل ساز است. تصور کنید کاربرانی که به اینترنت پرسرعت دسترسی ندارند آیا تمایلی دارند صفحه را مشاهده نمایند که در آن یک ViewState 40 کیلوبایتی وجود داشته باشد؟
این مشکل بویژه زمانی حادتر میشود که منطق برنامه ما ایجاب کند کارر بارها و بارها برای انجام کار خود مجبور به ارسال مجدد صفحه یا همان post back به سرور باشد.
با توجه به این مشکل من سعی کردم راه حلی را به کار گیرم که ViewState را فشرده کرده و مقدار قابل توجهی در پهنا باند مصرفی صرفه جویی به عمل آید.
این راه استفاده از GZipStream یا DeflateStream است که در دات نت 2 ضمیمه شده اند.
قبل از هرکاری نیاز داریم تا آرایه ای از بایتها را در حافظه فشرده سازی و از حالت فشرده خارج نماییم. برای همین من کلاسی ایجاد کرده ام که دو متد به نامهای Compress و Decompress دارد:

using System.IO;
using System.IO.Compression;
public static class Compressor {
public static byte[] Compress(byte[] data) {
MemoryStream output = new MemoryStream();
GZipStream gzip = new GZipStream(output,
CompressionMode.Compress, true);
gzip.Write(data, 0, data.Length);
gzip.Close();
return output.ToArray();
}
public static byte[] Decompress(byte[] data) {
MemoryStream input = new MemoryStream();
input.Write(data, 0, data.Length);
input.Position = 0;
GZipStream gzip = new GZipStream(input,
CompressionMode.Decompress, true);
MemoryStream output = new MemoryStream();
byte[] buff = new byte[64];
int read = -1;
read = gzip.Read(buff, 0, buff.Length);
while(read > 0) {
output.Write(buff, 0, read);
read = gzip.Read(buff, 0, buff.Length);
}
gzip.Close();
return output.ToArray();
}
}

برای استفاده از این کد، این کلاس را در فایلی با پسوند cs ذخیره میکنیم و آن را در پوشه App_Code در برنامه مورد نظرمان قرار میدهیم. اکنون برای فشرده سازی ViewState نیاز داریم تا دو متد به نامهای LoadPageStateFromPersistenceMedium و SavePageStateToPersistenceMedium را بازنویسی کنیم.


نکته این که در کد زیر از متغیری به نام __VSTATEبرای ذخیره سازی ViewState فشرده شده استفاده مینماییم. میتوانید این مورد را با مشاهده کد HTML صفحه ملاحظه کنید. سپس در متد LoadPageStateFromPersistenceMedium مقدار متغیر __VSTATE را خوانده و آن را از حالت فشرده خارج میکنیم:

public partial class MyPage : System.Web.UI.Page {
protected override object LoadPageStateFromPersistenceMedium() {
string viewState = Request.Form["__VSTATE"];
byte[] bytes = Convert.FromBase64String(viewState);
bytes = Compressor.Decompress(bytes);
LosFormatter formatter = new LosFormatter();
return formatter.Deserialize(Convert.ToBase64String(bytes));
}
protected override void SavePageStateToPersistenceMedium(object viewState) {
LosFormatter formatter = new LosFormatter();
StringWriter writer = new StringWriter();
formatter.Serialize(writer, viewState);
string viewStateString = writer.ToString();
byte[] bytes = Convert.FromBase64String(viewStateString);
bytes = Compressor.Compress(bytes);
ClientScript.RegisterHiddenField("__VSTATE", Convert.ToBase64String(bytes));
}
// The rest of your code here...
}

در متد اول ما تنها __VSTATE را که از کد Base64 را که از آن برای کدگذاری و فشرده سازی استفاده آن کرده بودیم را رمز گشایی و از حالت فشرده خارج کردیم.


در متد دوم دقیقا عمل عکس را انجام دادیمو حاصل را در فیلد مخفی __VSTATE قرار داده ایم.


شما همچنین متیوانید یک کلاس جدید به نام CompressedPage ایجاد نمایید که از System.Web.UI.Page ارث بری نماید و دو متد مذکور را در آن بازنویسی نمایید. سپس صفحات وب سایت خود را از این کلاس ارث بری نمایید تا دیگر لازم نباشد به ازای هر صفحه مجددا این کد را تکرار نمایید.


نکته این که پس از تست برنامه من متوجه شدم که این کار باعث کاهش 38 کیلو بایت به 17 کیلو بایت یعنی صرفه جویی 44 درصدی در مصرف پهنا باند شده است. آن هم به ازای هر کاربر و هر بار بارگذاری صفحه. مسلما چنانچه سایت شما بازدید کننده زیادی داشته باشد این کار باعث میشود صرفه جویی قابل توجهی در پهنا باند مصرفی ماهانه خود داشته باشد و هزینه کمتری به ازای خدمات میزبانی وب پرداخت نمایید.


این نکته را هم از یاد نبرید که اعمالی همچون فشرده سازی، رمزنگاری و ... منجر به اشغال منابع سرور مانند پردازنده و حافظه اصلی میشود. پس صرفا در مواقعی اقدام به رمزنگاری کنید که ضروری باشد.

تشکرات از این پست
دسترسی سریع به انجمن ها