|
ASP.NET Uygulamalarında Performansı Artırmak |
|
Gönderiliyor lütfen bekleyin... |
|
|
Bazı uygulamalar
için önemli olan bir girdiye doğruyu çıktıyı makul bir zamanda verebilmektir,
ancak ASP.NET gibi uygulama türlerinde hız ve performans çok önemli bir faktördür.
Hız ve performansın ASP.NET web uygulamalarında önemli olmasının en büyük nedeni
elbetteki uygulamaların web tabanlı olması ve uygulamanın çalışması için sunucudan
istemciye yüklenme gerekliliğidir. Uygulamanın içerdiği lojik ve bellek yönetimi
ne kadar iyi yapılırsa programın istemciye çıktıyı üretmesi o kadar hızlı olacaktır.
Dolayısıyla hızlı ver performansı yüksek olan ASP.NET uygulamaları geliştirmek
için geleneksel olan bazı kuralların bilinmesi ve bunların geliştirici tarafından
uygulanması gerekir. Bu yazıda ASP.NET uygulamalarının performansını artıracak
önemli ipuçlarından ve bazı klasik yöntemlerden bahsedeceğim.
Performans artırma işlemi kesin çizgilerle belirlenmiş bir kavram değildir.
Çünkü amacımız sistemin yapabileceklerini kısıtlamadan var olan özelliklerin
daha hızlı çalışmasını sağlamak. Bu yüzden bu yazıda anlatacağım bazı kaçınmamız
gereken noktaları bir çok projede zaten uygulamış olabilirsiniz. Bu, projenizin
yapısını değiştirmeniz gereklidir anlamına gelmez, ancak bundan sonraki projelerinizde
bu tür durumlara dikkat etmeniz gerekebilir.
Şimdi sırayla uygulamamızın performansını artırabilecek faktörleri ele alalım
:
1 - "Release Mode" Derlemesi Yapma
Bildiğiniz üzere .NET uygulamalarında iki tür derleme yapabilmekteyiz, Bunlar
: "Debug Mode" ve "Release Mode". Genellikle geliştirme
aşamasında derleme işlemini "Debug Mode"’ da yaparız. Çünkü "Debug
Mode" derlemesi programdaki bütün akışı bize görsel bir şekilde sağlar
ve koddaki hataları ayıklamamızı sağlar. Tabii bunu yapabilmenin ağır bir bedeli
vardır. Programın akışı ölçülebilecek derecede debug modda derlenmiş bir kodda
yavaşlayacaktır. Bunun sebebi hataları ayıklayabilmemiz için çıktı dosyalarına
ekstra bilgilerin(.pdb dosyaları) eklenmesi ve çalışma sırasında bu bilgilerin
yorumlanmasıdır. Çoğu zaman uygulama gerçek ortamda çalıştırılmadan önce Debug
Mode’dan Release Mode’a çekme işlemi unutulabiliyor. Dolayısıyla farkında olmadan
büyük bir performans kaybı olmakta. Programı "Release Mode" da derlemek
için Web.Config dosyasında aşağıdaki değişiklik yapılabileceği gibi VS.NET’te
proje özelliklerinden "Configuration Properties" seçeneğinden aktif
halae getirilebilir.
<compilation
defaultLanguage="c#"
debug="true"
/>
dsa
2
- Object Veri Tipini İhtiyaç Dahilinde Kullanmak
.NET platformunda her ver tipi Object sınıfından türediği için herhangi bir
değişkeni veya nesneyi object türünden bir değişkene atayabiliriz. Ancak object
türü referans türü olduğu için int, byte ve double gibi temel veri tiplerini
kolaylık olsun diye Object türünden değişkenlere atamamalıyız. Zira int,byte
ve double gibi değer türleri belleğin stack dediğimiz bölgesinde saklanırken,
sınıflar ve object türden nesneler belleğin heap bellek bölgesinde saklanır.
Mimari olarak farklı tasarlanmış iki bellek bölgesi arasında veri alışverişi
şu anki belleklerde her ne kadar çok fazla hız kaybı yaratmasa da bu tür işlemlerin
çok sık yapıldığı döngü gibi yapılarda önemli sayılabilecek bir performans kaybı
olabilir.
3 - "String" Ekleme İşlemlerinde
"StringBuilder" Kullanmak
String işlemleri her uygulamada sık sık yapılan işlemlerdir. Özellikle birden
fazla yazıyı ard arda yapıştırma işlemi çok sık yapılan işlemlerdir. String
veri türünün çok özel bir durumu vardır : İki yazıyı + operatörüyle ard arda
eklediğinizde sonuç olarak yeni bir string değişkeni döndürülür ve ard arda
eklenen diğer iki string bellekte orjinal halleriyle kalır. Bir örnek verelim:
string yazi1 = "csharp";
string yazi2 = "nedir.com";
string yazi1 =
yazi1 + yazi2;
Bu örnekte 3.satırdaki atama ile yazi1 değişkenine iki yazının birleştirilmiş
hali eklenecektir. Buraya kadar her şey normal. Ancak genelde şu şekilde bir
yanılgı olmaktadır. Programın icrası 3. satıra geldiğinde yazi1 değişkenin son
karakterinden sonraki bölümüne yazi2 eklenecektir. Ve dolayısıyla artık bellekte
"csharp" diye bir yazı kalmayacaktır. Ama bu böyle değildir. yazi1
değişkeni için bellekte yeni bir bölge tahsis edilir ve yazi1 ile yazi2 birleştirilip
bu birleşmiş yazının başlangıç adresi yazi1’in referansına atanır. Dolayısıyla
biz farkında olmasak ta bellekte bu işlemden sonra "csharp","nedir"
ve "csharpnedir" olmak üzere 3 tane string değişkeni bulunmaktadır.
Tabi biz "csharp" yazısını içinde tutan yazi1 değişkenine olan referansımızı
kaybettiğimiz için 3. satırdan sonra "csharp" yazısına erişemeyiz.
Verilen örnekte herhangi bir performans kaybının olmayacağı açıktır. Ancak döngülerle
metin dosyaları gibi büyük veri kümeleri üzerinde işlem yapıyorsak bunun etkisini
çok rahatlıkla hissedebiliriz. Bu tür bir etkiyi azaltmak için .NET sınıf kütüphanesinde
System.Text isim alanında StringBuilder isminde bir sınıf bulunmaktadır. Bu
sınıfın Append metodunu kullanarak iki yazıyı daha etkin bir şekilde birleştirebiliriz.
Sonuç olarak eğer bir program içinde yirmiden fazla uzun yazı dizisi birleştiriliyorsa
her iki metodun arasında fark rahatlıkla ölçülebilecek durumua gelmektedir.
İki yöntem arasındaki farkı daha iyi anlamak için okumanızı önerdiğim yazı :Metin(String)
İşlemlerinde Performansı Artırmak
4 - ViewState’in Etkin Kullanımı
ASP.NET’in en önemli yeni kavramlarından birisi de ViewState’dir. ViewState,
web kontrollerinin HTTP istekleri sırasında içeriklerinin sunucuya postalanması
bittiği anda HTML çıktısına eklenen veri kümesidir. ViewState özelliği aktif
olan web kontollerinin bulunduğu bir form herhangi bir şekilde yeniden yüklenmesi
sağlansa bile kontollerin içeriği değişmeyecektir. Halbuki klasik yöntemlerle
sunucudan gelen çıktıda bu tür bir eklenti olmamaktadır. ViewState’in gereksiz
yere aktif halde kalması büyük bir performans kaybına sebeb olacaktır. Çünkü
web formu sunucuya postalandıktan sonra web kontrollerinin ve web formlarının
içeriği ViewState’teki bilgilere göre yeniden yüklenir ve işlemler bundan sonra
devam eder. Ayrıca ViewState bilgileri DatGrid gibi içerisinde çok fazla veri
bulunduran web kontrolleri ile birlikte çok fazla şişecektir. ViewState verisine
ihtiyacımız yokken bu verilerin sunucuda oluşmasını sağlamak gereksiz veri trafiği
yaratcağı için bu durumlarda kontrolün yada web formunun ViewState özelliğini
pasif hale getirmeliyiz.
Bütün Web kontrollerinin bool türünden EnableViewState adında bir özelliği
bulunmaktadır. Bu özelliği false yaparak ViewState bilgisinin ilgili kontrol
için oluşmamasını engelleyebiliriz. Eğer ViewState özelliğini bütün form için
pasif konuma getirmek istiyorsak web formunun Page direktifinden sonra aşağıdaki
gibi kullanım mevcuttur.
<@Page EnableViewState = "false"@>
5 - Oturum(Session) Nesnesinin Etkin Kullanımı
Hemen hemen bütün türden web uygulamasında Session nesnesi kullanılmaktadır.
Session nesnesine yazmak ve session nesnesinden okuma yapmak sunucu açısından
o kadar da kolay bir iş değildir. Session nesnesinin aktif olduğu her bir sayfa
sunucuya ek yük bindirmektedir. Bu yüzden Session nesnesine ihtiyacımız yok
ise bu özelliği pasif konuma getirmekte fayda vardır. Bazı durumlarda Session
nesnesine sadece okuma amaçlı ihtiyaç duyabiliriz, bu durumda da Session nesnesine
sadece okuma amaçlı erişeceğimizi sayfada bildirerek belli ölçüde performans
kazanabiliriz.
Bir web formu için Session nesnesini pasif hale getirmek için yapmamız gereken
tek şey Page direktifinden sonra aşağıdaki gibi EnableSessionState="false"
ifadesini yazmak.
<@Page EnableSessionState = "false"@>
Aynı şekilde Session nesnesini sadece okunabilir yapmak için için EnableSessionState
= "ReadOnly" yazmak yeterli olacaktır.
6 - Gereksiz Postback İşlemleri
Bir web formunun ilk defa mı yoksa yeninden bir istek sonucu mu yüklendiğini
anlamak için Page sınıfının IsPostBack özelliği kullanılmaktadır. Özellikle
statik data bağlı kontrollerin bir web formunda kullanılması sırasında IsPostBack
kontrolünü kullanıp sonraki yüklemelerde verilerin yeniden kontrollere bağlanmasını
engellemeliyiz. Tabi bu durum için kontrole bağlı verinin statik olduğunu düşünüyoruz.
Bu özelliğin örnek bir kullanımı biçimi aşapıdaki gibi olabilir.
private void
OnPage_Load(...)
{
if(!Page.IsPostBack)
{
DataBagla();
}
}
|
7 - Dataları Application Nesnesinde Saklama
Bir çok veritabanı uygulamasında çok sık değişmeyen veriler dinamik bir şekilde
her bir web formundan yüklenmektedir. Üstelik bu işlem her oturum için tekrar
tekrar yapıldığı için sunucuya büyük bir yük bindirilmiş olur. Halbuki çok sık
değişmeyen bu tip veriler global düzeyde bellekte saklanıp, her bir oturum bu
veriye bu bellekteki nesneden erişirse hem web sunucusu büyük bir dertten kurtulacak
hemde web formlarının istemciye yüklenmesi daha kısa süre alacaktır. Örneğin
bu sitede yandaki kolonda bulunan dinamik menü tahmin edeceğiniz üzere veritabanından
gelmektedir. Bu menü çok uzun bir süre aynı kalacağı için her bir kullanıcı
siteye bağlandığında veritabanından bu menü listesini almak mantıklı değildir.
Bu tarz durumlarda genellikle başka türlü bellekleme işlemleri yapılmasına rağmen
bütün uygulama ve oturumlar için global düzeyde yönetilebilen Application nesneside
kullanılabilir. Siteye herhangi bir bağlantı yapıldığında Menü bilgileri Application
nesnesi yardımıyla belleğe alınır ve ardından bütün kullanıcılar zaten bellekte
olan bu veriye erişirse sunucu büyük ölçüde rahatlayacaktır. Bu durum daha çok
aynı siteye aynı anda çok fazla istemcinin bağlı olduğu durumlarda anlamlıdır.
Uygulama bazındaki değişkenleri Application nesnesi ile yönetebilmekteyiz. Örnekte
verilen Menü bilgisini bir defaya mahsus olmak üzere belleğe yüklemek için gloabal.asax
dosyasındaki Application_Start() metodunu kullanmamız yerinde olacaktır.
Yukarıdaki kullanıma bir örnek verelim :
//Global.asax
dosyası
public void Application_Start()
{
SqlCommand cmd = new SqlCommand("select
* from Menu",baglantinesnesi);
SqlDataAdapter adp = new
SqlDataAdapter(cmd);
DataTable dtMenu = new
DataTable("MENU");
adp.Fill(dtMenu);
Application["MakaleMenu"]
= dtMenu;
}
//Herhangi bir web formu
private void Page_Load()
{
DataTable menu = (DataTable)Application["dtMenu"];
grdiMenu.DataSource =
menu;
}
|
Not : Yukarıdaki
örnekte global düzeydeki Application nesnesindeki bir elemanın değerinin ne
şekilde elde edildiğine özellikle dikkat ediniz.
8 - Data Erişimini Optimize Etmek
Bir ASP.NET uygulamasının olmazsa olmaz bileşeni veritabanıdır. Veritabanları
çok sık kullanıldığıdan veriye erişim tekniğini en optimum biçimde ayarlamamız
çok önemlidir. Veri erişiminde eğer SQL Server kullanıyorsak derlenmiş veritabanı
bileşenleri olan Stored Procedure kullanmak, sadece ileri yönlü ve okuma amaçlı
veri erişimi yapıyorsak DataAdapter ve DataSet ikilisi yerine DataReader nesnelerini
kullanmak, eğer varsa ilgili veri kaynağına özgü olan data erişim bileşenlerini(SqlDataReader,OracleDataReader
vs.) kullanmak her zaman performansı olumlu yönde etkileyecektir.
9 - Ön Bellekleme (Caching) Yapmak
Ön bellekleme ASP.NET’in en önemli konularından birisidir. Ön bellekleme, bir
HTML çıktısının yeniden sunucu tarafından oluşturulmaksızın daha önceki istekler
sonucunda oluşturulmuş HTML çıktısını sunucunun belleğinde saklama ve gerektiğinde
bellekteki hazır veriyi istemciye gönderme işlemine denir. ASP.NET, IIS sunucusunun
ön bellekleme mekanizmasında da faydalanarak bir takım ön bellekleme mekanizmaları
sunmaktadır. ASP.NET ön bellekleme konusu çok ayrıntılı ve üzerinde ayrıca çalışılması
gereken bir konu olduğu için bu yazıda ön bellekleme konusunu ana hatlarıyla
inceleyeceğim. Ön bellekleme işleminin performansı neden artırdığı açıkca ortada.
Zira ASP.NET uygulamaları IIS sunucusunda açılan ’worker process’ ler sayesinde
derlenip HTML çıktısına dönüştürülür. Derleme ve çıktıyı üretme işlemi zaman
alan asıl bölüm olduğu için çok sık değişmeyen sayfaları bir ön bellek mekanizması
ile her istekte bulunulduğunda yeniden dosya sisteminden okunmasını ve derlenmesini
engellemeliyiz. Yine şu an bulunduğunuz siteden örnek verelim : Bu sitenin anasayfası
gün içinde çok fazla değişmeyecektir. Dolayısıyla anasayfaya her istekte bulunan
oturum için asp.net motorunu devreye sokmak hem sunucuyu yoracaktır hemde göreceli
olarak sayfaların kullanıcı tarafından ulaşılması fazla zaman alacaktır. Bu
durumda yapılması gereken bu sayfanın günlük olarak yada parametrik olarak ön
belleklenmesidir.
ASP.NET üç tür ön bellekleme mekanizmasını destekler. Şimdi sırasıyla bu ön
bellekleme mekanizmalarını inceleyeceğiz.
Output Caching(Çıktı ön bellekleme)
En basit tanımıyla "output caching", bir sayfanın tümünün belli bir
süre için yada bazı koşulların geçerliliği sağlanıncaya kadar sayfanın HTML
formatında belleklenmesi ve gerektiğinde bu bilginin istemciye herhangi bir
işlem yapılmadan gönderilmesidir. Bir sayfanın iki dakikalık süreyle ön belleklenmesi
ve bu iki dakikadan sonra ön belleğin silinip çıktının yeniden üretilmesini
sağlamak için aspx dosyalarında OutputCache direktifi aşağıdaki gibi
kullanılır.
<%@OutputCache Duration = "120" VarByParam = "none"%>
Yukarıda, VaryByParam zorunlu bir parametre olmasına rağmen herhangi bir değer
verilmemiştir. Ön bellekleme işlemi bu durumda iki dakikalık aralıklarla HTTP_User_Agent
çevre değişkeninin değerine göre yapılmaktadır. Örneğin Internet Explorer tarayıcısı
için ön belleğe alınmış bir HTML çıktısı, Netscape yada Opera gibi bir tarayıcda
geçerli olmayabilir. Dolayısıyla sunucu ön bellekten okuma işlemini sadece aynı
çıktıyı yorumlayabilecek tarayıcılar arasında gerçekleştirilecektir. Ön bellekleme
işleminin etkisini anlamak için o anki saati ekrana yazan bir sayfa tasarlayın
ve bu sayfanın OutputCache Duration özelliğini 10 yapıp programı çalıştırın.
Eğer sadece her 10 saniyede bir saatin doğru olduğunu gözlemlerseniz ön bellekleme
işlemini başarmışsınız demektir.
Bazı durumlarda sayfadaki ön bellekleme işlemini POST yada GET metoduyla sayfaya
gelen herhangi bir değişkenin değerinin değişip değişmediğine göre de yapmak
isteyebiliriz. Bu durumda yapmamız gereken ilgili değişkenleri ; karakteri ile
ayırarak VaryByParam parametresi olarak değiştirmek. Örneğin sayfaya QueryString
olarak gelen ID ve Login değişkenlerinin değişmesine göre ön bellekleme yapmak
istiyorsak OutputCache direktifi aşağıdaki gibi kullanılmalıdır.
<%@OutputCache Duration = "120" VarByParam = "ID;Login"%>
OutputCatch direktifinin parametreleri bu kadarla sınırlı değildir. Örneğin
VarybyHeader, VaryByCustom gibi kriterler de belirtmemiz mümkün. OutputCache
direktifi ile ilgili ayrıntılı katalog bilgisi için MSDN yardım dökümanlarına
başvurabilirsiniz.
Ön bellekleme performansı artıran bir faktör olmasına rağmen yanlış biçimde
ve sonuçları tam olarak düşülmeden kullanıldığı takdirde aklımıza gelemeyecek
problemlere neden olabilir. Bu yüzden istemcinin ön belleklenmiş veya yeniden
üretilen veriyi alıp almaması arasındaki farkı iyi analiz etmek gerekir.
Fragment Caching(Kısmi ön bellekleme)
Bazı durumlarda sayfanın tümünü ön bellekleme yerine sayfada bulunan web kontrollerinin
ön belleklenmesini isteyebiliriz. Özellikle header,footer, menu gibi kullanıcı
kontrolü (user control) olabilecek bileşenler çok sık değişmediği için anasayfamıza
ekleyeceğimiz bu tür kullanıcı kontrollerini ön beleğe alabilmekteyiz. Kullanıcı
kontrolerinin ön belleğe alınma işlemi normal bir sayfanın ön belleğe alınma
işleminden hiç bir farkı yoktur. Kullanıcı kontrollerini içeren .ascx sayfalarında
OutputCaching direktifini kullanarak kullanıcı kontrolünün ön belleklenmesini
sağlayabiliriz. Yine aynı şekilde VarByParam, Duration, VaryByHeader gibi parametreleri
de kullanabilmekteyiz.
Data Caching(Veri ön bellekleme)
Daha önce performansı artırmanın yollarından birisinin bütün oturumların erişebileceği
Application nesnesini kullanmak olduğunu söylemiştik. Ancak global düzeyde erişim
sağlanabilen Application değişkeni
ön bellekleme için özellştirilmemiş bir nesne modeli olduğu için kullanımı çok
esnek değildir. ASP.NET yeni bir veri modeli ile data ön belleklemesi yapmaktadır.
Bu veri modelini temsil eden değişken yine bütün oturumlar tarafından erişilebilen
Caching değişkenidir. Caching değişkenin kullanımı tıpkı Application değişkeninin
kullanımı gibidir. Örneğin bir DataSet nesnesini ön beleğe alıp diğer bütün
oturumlar tarafından erişilebilmesine olanak sağlamak için aşağıdaki gibi ifade
yazabiliriz.
DataSet ds = new DataSet();
Cach["MENU"] = ds;
Aynı şekilde ön bellekteki DataSet nesnesini elde etmek için aşağıdaki satırı
yazmamız yeterli olacaktır.
DataSet dsOnBellek = (DataSet)Cache["MENU"];
Cache nesnesinin Application nesnesinden en önemli farkı ön bellekteki nesnelerin
belleğin durumuna göre sunucu tarafından silinebileceğidir. Application değişkeninde
böyle bir durum olduğu takdirde uygulama hatalı çalışabilecektir. Ancak Cache
değişkeninde ilgili değişkene erişilmek istendiğinde eğer veri ön bellekte bulunamaz
ise veri orjinal kaynağından tekrar alınabilmektedir. Bu durum hem belleğin
efektif kullanımını sağlar hemde uygulamamızda herhangi bir hatanın meydana
gelmsini önler.
Cache sınıfının Insert() metodu yardımıyla ilgili veri ön belleklemesinin ne
zaman sonra ereceğini ve ön bellekleme işleminin hangi kriterlere göre yapılabileceğini
de belirtmek mümkündür. Bu yazıda amacımız caching mekanizmasını tüm ayrıntılarıyla
anlatmak olmadığı için caching ile ilgili ayrıntılı bilgi için MSDN’e başvurumanızı
öneririm.
Sonuç
Bu yazıda en yüksek performansta çalışacak ASP.NET web uygulamaları geliştirmek
için nelere dikkat etmemiz gerektiğini inceledik. Geliştirdiğiniz projelerde
yularıda değindiğimiz dokuz maddeyi bir "check list" şeklinde kullanmanızı
öneririm.
Makale:
ASP.NET Uygulamalarında Performansı Artırmak ASP.NET Sefer Algan
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|