ASP.Net ile veri çekme testleri..

Zamanında overclock ile epeyce uğraştım, çok
fazla sayıda donanımı deneme ve test etme imkanı buldum. Sonrasında yazılım
tarafı ağır basınca overclock işini maziye gömdüm. Kaç zamandır acaba DataTable
mi kullansam, foreach mı kullansam veya DataAdapter mi kullansamın hesabını
yapıyordum, diğer yandan acaba hangisi daha performanslı çalışır veya kullanıcı
tarafında hangisi daha sorunsuz görüntülenebilir gibi düşünceler içerisindeydim.
Madem eski hız aşırtmacılardanım kendimce bir test (benchmark)
platformu hazırlayıp işe koyulayım dedim. Belki yanlış işlemler yapmış
olabilirim, göz ardı ettiğim noktalar olabilir bunları eğer paylaşırsanız çok
sevinirim.

Test sistemi;

Acer 5920G Dizüstü Bilgisayar (T7100 @ 1,8Ghz İşlemci, 4GB 800Mhz Bellek)
Windows Vista Ultimate (32-Bit) (Güncel), Internet Explorer 7, Mssql 2005, FrameWork 3,5 (Güncel),
Visual Studio 2008

Test hakkında:
Sql server, IIS ve İstemci aynı bilgisayardır, sonuçları ms cinsinden
etkilemiştir fakat tüm testler için aynı ortam olduğu için % olarak çok bir fark
olacağını sanmıyorum.
Testleri en çok kullanılan veri listeleme nesneleri olan GridView ve
DataList içinde listeledim.
Her testi 3 kez tekrarlayarak ortalamasını aldıktan sonra kayda geçtim.
SQL Server Profiler sadece ilgili testi yaparken açıktı, diğer durumlarda
kapalı.
Grafiklerdeki veriler milisaniye (ms) cinsinden olup, Sql S.P.
SQL
Server Profiler kısalıtılmış halidir.
Testler sırasında  EnableViewState=”false” durumundadır, nedenlerin başında
foreach döngüsünde viewstate boşken gridview ve datalist’ te dolu olması.
Haksızlık olmasın diye kapattım.

Sırasıyla 1000,10.000 ve 100.000 kayıt üzerinde denemeler yapılmıştır.
Testler arasındaki geçişleri // işaretlerini kaldırarak ve pageload daki method ismini değiştirerek gerçekleştirdim.
Hatırlatma: Milisaniye cinsinden değerler azaldıkça performansın arttığını
anlıyoruz.

Testte kullanılan kodlar ve tablonun yapısı:
Testte Vegawin ticari yazılımının kullanıcı işlemlerini loglayan tablosunu
kullandım, içerisinde 530.000 adet kayıt bulunan bir tablo, test sırasında
dışarıyla bağlantısı olmadığından herhangi bir ekleme yada silme işlemi söz
konusu değildi.

CREATE TABLE [dbo].[TBLLOG] (
[IND] int IDENTITY(100, 1) NOT NULL,
[FIND] int NULL,
[DIND] int NULL,
[PID] smallint NULL,
[TARIH] datetime NULL,
[MAKINE] nvarchar(50) COLLATE Turkish_CI_AS NULL,
[USERID] int NULL,
[BELGE] int NULL,
[BELGENO] int NULL,
[EYLEM] int NULL,
[ACIKLAMA] nvarchar(100) COLLATE Turkish_CI_AS NULL
)
ON [PRIMARY]
GO
[/html]

Yeri gelmişken bana Object Oriented konusunda yol gösteren ve herzaman vakit ayırıp sorularımı cevaplayan Yunus Emre arkadaşıma teşekkürlerimi sunuyorum.

Class.cs
[/html]
public class veritabani
{
static private string baglanti()
{
return @"Data Source=sunucu;Initial Catalog=veritabani;Persist Security Info=True;User ID=kullaniciadi;Password=sifre;pooling=true";
}
public static DataTable DataTableGetir(string strSQL)
{
SqlConnection conn = new SqlConnection(baglanti());
SqlCommand cmd = new SqlCommand(strSQL, conn);
cmd.CommandTimeout = 0;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
try
{
da.Fill(ds, "TABLE");
return ds.Tables["TABLE"];
}
catch
{
}
finally
{
if (conn != null && conn.State == ConnectionState.Open)
{
conn.Close();
}
conn = null;
}
}
}
[/html]
[/html]
public partial class _Default : System.Web.UI.Page
{
string kayitsayisi="100000";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
griddoldur2();
}
}

protected void griddoldur1() {
DateTime baslangic = DateTime.Now;

DataTable dt = veritabani.DataTableGetir("Select top "+kayitsayisi+" * from TBLLOG");
GridView1.DataSource = dt;
GridView1.DataBind();

//foreach (DataRow dr in dt.Rows)
//{
//Response.Write("

");
//Response.Write("

");
//Response.Write("

" + dr["IND"].ToString() + " - " + dr["FIND"].ToString() + " -
" + dr["DIND"].ToString() + " - " + dr["PID"].ToString() + " - " + dr["TARIH"].ToString() + " -
" + dr["MAKINE"].ToString() + " - " + dr["USERID"].ToString() + " - " + dr["BELGE"].ToString() + " -
" + dr["BELGENO"].ToString() + " - " + dr["EYLEM"].ToString() + " - " + dr["ACIKLAMA"].ToString() + "

");
//}

DateTime bitis = DateTime.Now;
TimeSpan fark = bitis - baslangic;
sonuc.Text = fark.TotalMilliseconds.ToString() +" mili saniye";
}

protected void griddoldur2() {
DateTime baslangic = DateTime.Now;
SqlConnection sqlConn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["baglanti"].ToString());
SqlDataAdapter sqlAdap = new SqlDataAdapter("Select top " + kayitsayisi + " * from TBLLOG", sqlConn);
DataSet Ds = new DataSet();
sqlAdap.Fill(Ds);
GridView1.DataSource = Ds;
GridView1.DataBind();
DateTime bitis = DateTime.Now;
TimeSpan fark = bitis - baslangic;
sonuc.Text = fark.TotalMilliseconds.ToString() + " mili saniye";
}
}
[/html]

Grafiklerle test sonuçları
asp.net 1000 kayıt performansı
asp.net 10000 kayıt performansı
asp.net 100000 kayıt performansı

Test sonuçları ve gözlemlerim:
Kayıt sayısı arttıkça foreach döngüsünün başarısıda ciddi anlamda artıyor.
Ekstra bir ayar yapmadığımdan dolayı veriler geldikçe tarayıcıya basılıyor ve bu
sayede kullanıcı diğer yöntemlerde verinin tam yüklenmesini beklerken bu yöntemde uzun süreli beklemeden
kurtulmuş oluyor, kayıtların tamamı döndükçe döndükçe geliyor ve aynı zamanda
düşük konfigürasyonlu bilgisayarlarda oluşacak olan donma ve yanıt vermeme
durumu ortadan kalkmış oluyor. 100.000 kayıt
ciddi bir rakam uygulamada belkide hiç karşılaşılmayacak bir rakam fakat neler
olduğunu görmek adına denemek istedim, veriler ekrana basılırken ve basıldıktan
sonra zaman zaman tarayıcınızın cevap vermemesine sebep oluyor, yinede sorunsuz
bir şekilde listeleniyor. Burada
belkide sql sunucu, istemci ve iis in bir arada olmasıda önemli bir faktör
olarak görülebilir fakat bellek kullanımı ve işlemci kullanımına baktığımda
anormal bir durum söz konusu değildi. Bu sadece bir testti, test sonuçlarından
sonra foreach çok daha performnslı diye bu yöntemi kullanıp, gridview ve
datalist gibi nesnelerin nimetlerinden yararlanmamak tabiki söz konusu olamaz.
Bu kadar çok kaydı ciddi raporlarda almadıktan sonra kolay kolay web de
karşımıza sanmıyorumki çıksın, az kayıt sayısında da devasa farklar oluşmuyor.
Burda dikkatimi çeken nokta ise DataTable nin performansı oldu, 1000 ve 10.000
kayıtta DataAdapter' e fark atıp foreach ile kafa kafa ya giderken 100.000
kayıtta tepetaklak olması beni şaşırttı. İlk fırsatta bu testi yeniden yapıp
sonuçları paylaşacağım. Asıl bundan sonra yapacak olduğum Insert ve Update
işlemleri beni çok meraklandırıyor, bakalım bu testlerde neler olacak. Kendime
göre çıkardığım sonuçta DataTable kullanmak en sağlıklısı, ama unutmayınki her
yiğidin bir yoğurt yiğişi vardır. :)