Jump to content
Forumu Destekleyenlere Katılın ×
Paticik Forumları
2000 lerden beri faal olan, çok şukela bir paylaşım platformuyuz. Hoşgeldiniz.

C# List 'de bir performans sorusu


Öne çıkan mesajlar

Mesaj tarihi:
Selamlar, kendimce C# 'da birşeyler karalıyorum. Şimdi bir programım var ve bunda elemanlar oturum açmak zorundalar.

Ben bu oturumlara bir IP limit getirerek tek IP'den belli bir oturum açılmasını istiyorum. Bunun için şöyle bir yol izliyorum.

private static List IpPool = new List();
private static IpAdress ClientIP;

public Enable() {
//burada eleman oturum açtığı zaman işlemler var
if(IpPool.Count(c => c == ClientIP) >= 5) {
//Burada adamı direkt disconnect edeceğiz.
}
IpPool.add(ClientIP);
}

public Disconnect() {
//Burada oturum kapatıldığı zaman işlemler var
IpPool.remove(ClientIP);
}

Sistem çalışıyor ancak c# 'da orta seviye olduğum için performans olarak daha sağlıklısını yapabilir miyim ?
Mesaj tarihi:

// yeni gelen IPAddress, yani sanıyorum ClientIP
var ip = ...;

var pool = new Dictionary<IPAddress, List<IPAddress>>();

List<IPAddress> sessions = null;

if(dict.TryGetValue(ip, out sessions))
{
// bu ip'den gelen başka sessionlar da varmış

if(sessions.Count >= 5)
{
// ve sayısı 5'ten fazlaymış

// (*) 4. session'dan sonrakilerin tümünü al
var fazlalik = sessions.Skip(4).ToList();

// (**) aşağıdakilerde Remove çağırmak yerine direkt 4. elemana kadar olan kısmı alarak yeni liste oluştur
pool[ip] = sessions.Take(4).ToList();

// (***) diğer session'ları artık disconnect edebilriz
foreach(var session in fazlalik)
Disconnect(session);
}
}
else
{
// başka session yokmuş, hem listeyi oluşturalım
// hem de sessions objesine atayalım ki aşağıda kullanabilelim
sessions = new List<IPAddress>();
pool[ip] = sessions;
}

sessions.Add(ip);



Bi dictionary'ye TryGetValue ya da [] operatörü ile erişmenin complexity'si O(1), aynı şekilde bi listenin eleman sayısına erişmek de O(1). O yüzden burdaki tek bottleneck (***) ile işaretlediğim kısımdaki Disconnect çağıran kısım.geri kalanı hep ufak tefek işlemler.

Yalnız bu collection'lar thread safe değil, o yüzden özellikle de 1'den fazla client aynı anda geldiğinde beklendiği gibi davranmaması muhtemel. Dictionary yerine ConcurrentDictionary, List yerine BlockingCollection kullanılabilir ama (*) ve (**) ile işaretli kısımlar olduğu sürece içerdeki BlockingCollection'un da pek bi anlamı kalmayacak. Neyse artık, ona da eğer client connect/disconnect olurken sıkıntılar yaşarsan (session'ların görünmemesi gibi) bakarız sdf
Mesaj tarihi:
Orada zaten foreach'e sokmama gerek yok ya. Direkt olarak break yapıp sonlandırırım. Hata mesajı verdirmeye verelim.

O zaman sanıyorum daha çok işe yarar

----

Birde abi benim anlamadığım kaçırdığım nokta şurası. "pool" diye oluşturduğumuz Dictionary 'e eklemeden başka hiçbirşey yapmıyoruz biz. Yani herhangi bir kontrol v.b birşey yok sadece ekleme var görebildiğim kadarıyla.

"sessions" 'a ekleme yapıp ondan sorguluyoruz. O zaman "pool" zımbırtısını neden oluşturup içine ipleri ekliyoruz.
Mesaj tarihi:
Bu kod web serverdami mi yoksa console app gibi birseymi? Web based ise concurrency olayi dogru. Sync primitives kullanman gerek yada bahsedilen thread safe yapilardan. Yok single threaded app ise ve ram in yettigince yazdigin kod iyidir bana kalirsa.
Mesaj tarihi:
Valla pool'un fonksiyonunu ben de anlamadım, sadece liste performansını iyileştirmeye odaklandım sdf

Yoksa session instance'ına direkt erişmeden disconnect nasıl olur bilmiyorum.
Mesaj tarihi:
https://dotnetfiddle.net/xWm66T

Şöyle birşey yaptım seninkinden yola çıkarak. Her IP'yi tek tek list'de tutacağıma dictinory'de tutup yanına int ile kaç kere girildiğini artırıyor yada azaltıyorum.

Bu nasıl?
  • 3 hafta sonra ...
Mesaj tarihi:
List sınıfı yeterince performanslıdır(c# pointerları kullanarak iyi algoritmayla listeler sana sadece fonksiyonu çağırmak kalır).Ama ben daha fazlasını istiyorum dersen memcache, redis gibi distirbuted da çalışabilen Key-Value store lazım. Böylece tüm sunucuların(eğer birden fazlaysa) birbirlerinden haberdar olarak (threadsafe de) İp adreslerini ramde key olarak tutarak tam istediğine ulaşabilirsin.
×
×
  • Yeni Oluştur...