Arşiv

Etiketlenen yazılar for

C# Performans Analiz Sınıfı

20 Kasım 2011 Yorum yapılmamış

Geliştirmekte olduğumuz uygulamalarda performans analizi yapmak için genellikle Stopwatch sınıfını kullanırız.

Aşağıdaki sınıf’ı kullanarak uygulamanın her method‘unu kolay analiz edebiliriz;

public class PerformansAnaliz
{
	public TimeSpan ToplamSure { get; private set; }
	public TimeSpan OrtalamaSure { get; private set; }

	public static PerformansAnaliz Yeni()
	{
		return new PerformansAnaliz();
	}

	public void Olcumle(Action Method, int TekrarAdet = 1)
	{
		var sw = Stopwatch.StartNew();
		for (int iLoop = 0; iLoop < TekrarAdet; iLoop++)
		{
			Method();
		}
		sw.Stop();
		OrtalamaSure = new TimeSpan(sw.Elapsed.Ticks / TekrarAdet);
		ToplamSure = sw.Elapsed;
	}
}

Euler – 8

16 Kasım 2011 1 yorum

Euler serisinin sekizinci yazısında, Project Euler’in 8. sorusunu çözeceğiz;

Orjinal Soru; Find the greatest product of five consecutive digits in the 1000-digit number.

7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450

Türkçesi; 1000 haneli rakamdan yan yana gelen en büyük 5 haneli rakamı bulunuz.

7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450

Önce siz çözmeyi deneyin, çözemezseniz Devamını oku…

Generic Dictionary sınıfına karıştırıcı (shuffle) Extension Method yazalım

03 Ekim 2011 Yorum yapılmamış

Winamp MP3 oynatıcısında çalma listesini (playlist) rastgele sıra ile karıştırabiliyorsunuz. Benzer özelliği kendi projelerimizde uygulamak isteyebiliriz.

Daha önce, C# ile Dizi Karıştırma yazısında bir dizi’yi (List<T>) nasıl karıştıracağımızı incelemiştik.

Bu yazı ile Karıştırma (Shuffle) yeteneğini Generic Dictionary (Dictionary<TKey, TValue>) ekleyeceğimizi inceleyeceğiz.

İlk olarak, ExtensionManager isminde static bir sınıf oluşturalım;

public static class ExtensionManager
{
	public static Dictionary<TKey, TValue> Shuffle(this Dictionary<TKey, TValue> liste)
	{
		Random r = new Random();
		return liste.OrderBy(x => r.Next()).ToDictionary(item => item.Key, item => item.Value);
	}
}

ExtensionManager sınıfının Shuffle() isminde bir method’u var.

Bu method, Random sınıfından yeni bir instance‘ın Next() method’unu kullanarak, liste değişkeninin her bir elemanını rastgele bir değerle sıralıyor.

Böylece, Shuffle() method’u her çağırıldığında liste değişkeninin elemanlarının rastgele sıralandığını görüyoruz.

Örnek Kullanım;

Dictionary<int, string> liste = new Dictionary<int, string>();

for (int iLoop = 0; iLoop < 5; iLoop++)
{
	liste.Add(iLoop, "Eleman " + iLoop);
}
//0, Eleman 0
//1, Eleman 1
//2, Eleman 2
//3, Eleman 3
//4, Eleman 4

Dictionary<int, string> karistirilmis = liste.Shuffle();
//2, Eleman 2
//1, Eleman 1
//3, Eleman 3
//0, Eleman 0
//4, Eleman 4

For – ForEach – List.ForEach performans karşılaştırması

31 Ekim 2010 1 yorum

Bir dizinin tüm elemanları üzerinde bir aksiyon gerçekleştirmemiz gerektiğinde, sıklıkla şu üç yoldan birini kullanırız;

  • For döngüsü
  • ForEach Döngüsü
  • List generic sınıfının ForEach extension method’u

Şimdi basit bir örnek ile bu üç yöntemi karşılaştıralım (*);

(* Not : Karşılaştırmalar; Windows7 64bit kurulu, Core2Duo 3.0 GHz ve 4 GB Ram’li bilgisayarımda yapılmıştır. Sadece fikir verme amaçlıdır, farklı durumlarda faklı sonuçlar ile karşılaşılabilir.)

Öncelikle parametre olarak Generic List (List<T>) alan üç tane method yazalım;

private static long ToplamFor(List<int> Liste)
{
	long Sonuc = 0;
	int ListeAdet = Liste.Count;

	for (int iLoop = 0; iLoop < ListeAdet; iLoop++)
		Sonuc += Liste[iLoop];

	return Sonuc;
}

private static long ToplamForEach(List<int> Liste)
{
	long Sonuc = 0;

	foreach (int Rakam in Liste)
		Sonuc += Rakam;

	return Sonuc;
}

private static long ToplamForEachExtension(List<int> Liste)
{
	long Sonuc = 0;

	Liste.ForEach(Rakam => Sonuc += Rakam);

	return Sonuc;
}

Aynı testi 10 defa gerçekleştirip, ortalamasını alacak bir test fonksiyonu yazalım. Yazacağımız fonksiyonu test listesinde olacak eleman adedini parametre olarak alacak;

private static void Testler(int ListeElemanAdet)
{
	List<int> ForSureler = new List<int>();
	List<int> ForEachSureler = new List<int>();
	List<int> ForEachExtensionSureler = new List<int>();

	List<int> TestVerisi = Enumerable.Range(0, ListeElemanAdet).ToList();

	Stopwatch sw = new Stopwatch();

	for (int iLoop = 0; iLoop < 10; iLoop++)
	{
		sw.Restart();
		ToplamFor(TestVerisi);
		sw.Stop();
		ForSureler.Add(sw.ElapsedTicks);

		sw.Restart();
		ToplamForEach(TestVerisi);
		sw.Stop();
		ForEachSureler.Add(sw.ElapsedTicks);

		sw.Restart();
		ToplamForEachExtension(TestVerisi);
		sw.Stop();
		ForEachExtensionSureler.Add(sw.ElapsedTicks);
	}

	Console.WriteLine("For Döngüsü ({0} Eleman) : {1}", ListeElemanAdet, ForSureler.Average());

	Console.WriteLine("ForEach Döngüsü ({0} Eleman) : {1}", ListeElemanAdet, ForEachSureler.Average());

	Console.WriteLine("ForEach Extension ({0} Eleman) : {1}", ListeElemanAdet, ForEachExtensionSureler.Average());
}

Artık uygulamamızın test fonksiyonunu kullanacak son kod parçasını yazabiliriz;

public static void Main(string[] args)
{
	Console.WriteLine("Test Başladı");

	Testler(1000);
	Testler(5000);
	Testler(10000);
	Testler(50000);
	Testler(100000);
	Testler(500000);
	Testler(1000000);
	Testler(5000000);
	Testler(10000000);
	Testler(50000000);

	Console.WriteLine("Test Bitti");

	Console.ReadLine();
}

Bakalım yaptığımız testler nasıl sonuç vermiş;

For - ForEach - ForEach extension Performans Karşılaştırması / Ekran Görüntüsü

Sonuçlardan aşağıdaki tabloyu çıkarttım;

Test Verisi For ForEach ForEach Extension
1.000 71,1 121,5 79,7
5.000 34,3 92,2 55,6
10.000 70,0 185,1 110,4
50.000 349,3 918,4 568,3
100.000 715,2 1.902,7 1.159,0
500.000 3.583,3 9.379,3 5.600,0
1.000.000 7.260,4 18.877,9 11.242,8
5.000.000 37.927,2 96.096,9 57.845,4
10.000.000 74.553,5 192.621,6 115.559,6
50.000.000 371.698,1 956.394,4 572.776,7

İlk olarak 50.000 elemana kadar olan listeler için karşılaştırma yapalım;

For - ForEach - ForEach extension Performans Karşılaştırması / 50.000 elemana kadar inceleme

Son olarak 50.000.000 elemana kadar olan listeler için karşılaştırma yapalım;

For - ForEach - ForEach extension Performans Karşılaştırması / 50.000.000 elemana kadar inceleme

Euler – 3

26 Ağustos 2010 1 yorum

Euler serisinin üçüncü yazısında, Project Euler’in 3. sorusunu çözeceğiz;

Orijinal soru; The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?

Türkçesi; 13195 rakamının asal çarpanları 5, 7, 13 ve 29′dur.
600851475143 rakamının en büyük asal çarpanı kaçtır?

Önce siz çözmeyi deneyin, çözemezseniz Devamını oku…

Bu kodda ne yanlış var? – 4

19 Temmuz 2010 5 yorum

Bowling skorlarını hesaplayan bir uygulama yazıyoruz.

2 oyuncunun 3 oyunda aldığı skorları hesaplayan aşağıdaki kodu yazdık ve çalıştırdık.

Fakat rakamlarda bir terslik var sanki. Sizce problem nedir ve nasıl düzeltebiliriz?

using System;

class Program
{
	static void Main(string[] args)
	{
		int[,] PuanTablosu = { {101, 128, 143}, {123, 115, 116} };

		int OyuncuPuan = 0;

		for (int iLoop = 0; iLoop < = PuanTablosu.GetUpperBound(0); iLoop++)
		{
			for (int yLoop = 0; yLoop <= PuanTablosu.GetUpperBound(1); yLoop++)
			{
				OyuncuPuan += PuanTablosu[iLoop, yLoop];
			}

			Console.WriteLine("Oyuncu {0} skor: {1}", iLoop + 1, OyuncuPuan);
		}

		Console.ReadLine();
	}
}

Kısa Sınav – 12

18 Şubat 2010 2 yorum

Kod yazma yeteneklerimizi ölçebileceğimiz sitelerden Codility‘de test olarak yapabileceğiniz bir soru bulunuyor. Aşağıdaki görselde soruyu görebilirsiniz.

Codility sitesinde yayınlanan demo test

Benim çözümüm devam eden sayfada. Sizde çözümünüzü yazın bakalım.

Devamını oku…

Normal For ve Paralel For Döngülerinin Karşılaştırması

08 Aralık 2009 Yorum yapılmamış

Yazdığımız uygulamaların olmazsa-olmaz’larından birisi de, for döngüleridir.

Ne kadar basit’te olsa, ne kadar karmaşık’ta olsa, mutlaka uygulamalarımızda for döngülerine ihtiyaç duyarız ve sıklıkla kullanırız.

Bu makaleyi okumaya devam etmeden önce, .Net Framework 4.0 ile birlikte gelecek olan Task Parallel Library hakkında yazdığım şu yazıyı (TPL (Task Parallel Library) – Task Class) okumanızı tavsiye ederim.

Task Parallel Library ile gelen Parallel sınıfının For methodunu kullanarak, Multi-Core destekli for döngüleri oluşturabiliriz.

Multi-Core destekli olması, Multi-CPU (birden çok CPU içeren) bilgisayarlarda, döngünün CPU’lara dağıtılabilmesini sağlıyor.

Parallel Library‘den önce for döngüsü;

//10 adımlı döngü (0 dahil, 10 hariç)
for (int iLoop = 0; iLoop < 100; iLoop++)
{
	// Yapılacak İş
}

Parallel Library ile for döngüsü;

//10 adımlı döngü (0 dahil, 10 hariç)
Parallel.For(0, 10, iLoop => {
	// Yapılacak İş
});

Parallel.For metodunu kullarak örnek bir proje hazırladım, projenin kaynak kodlarına buradan ulaşabilirsiniz.

NormalFor_ParallelFor_1

Uzun tek bir döngü yazmak yerine, içiçe iki döngü yazdım, böylece, CPU ve İşletim Sistemi’nin çok adımlı döngülerde yaptığı iyileştirmeleri bir miktar azaltmayı ve daha doğru bir sonuç elde etmeyi amaçladım.

Döngülerden bir tanesini gene de uzun tuttum (100.000.000 – Yüz Milyon Adım), böylece, eğer Framework’ün kendisi döngülerde iyileştirme yapıyorsa, bunları yakalamayı hedefledim.

Diğer döngüyü ise nispeten daha kısa (500 – Beş Yüz) tuttum.

NormalFor_ParallelFor_2

Böylece toplamda 50.000.000 (Elli Milyar) adımlı döngü oluşmuş oluyor.

Gelelim, kodlara;

private void btnNormalDongu_Click(object sender, EventArgs e)
{
	int Sayac = 0;
	Stopwatch sw = Stopwatch.StartNew();
	for (int iLoop = 0; iLoop < (int)txtTekrarAdedi.Value; iLoop++)
	{
		for (int yLoop = 0; yLoop < (int)txtDonguAdedi.Value; yLoop++)
		{
			Sayac++;
		}
	}
	sw.Stop();

	lblNormalDonguSonuc.Text = string.Format("{0:0,0} ms.", sw.ElapsedMilliseconds);
}

ve

private void btnParalelDongu_Click(object sender, EventArgs e)
{
	int Sayac = 0;
	Stopwatch sw = Stopwatch.StartNew();
	Parallel.For(0, (int)txtTekrarAdedi.Value, i => {
		Parallel.For(0, (int)txtDonguAdedi.Value, y => {
			Sayac++;
		});
	});
	sw.Stop();

	lblParalelDonguSonuc.Text = string.Format("{0:0,0} ms.", sw.ElapsedMilliseconds);
}

Teker teker butonlara bastığımızda, for döngüleri çalışacak ve sonuçları Label’larda göreceğiz.

Uygulamayı kendi bilgisayarımda çalıştırdığımda aldığım sonuçlar;

NormalFor_ParallelFor_3

Normal for döngüsü: 888.700 ms. (yaklaşık 14 dakika 48 saniye)

Paralel for döngüsü: 219.326 ms. (yaklaşık 3 dakika 39 saniye)

Aradaki fark: 75%

Uygulamayı çalıştırdığım bilgisayarın özellikleri;

NormalFor_ParallelFor_4