Yük testi: saniyede bir talep nasıl oluşturulur?


14

Zeroc-ICE üzerinde çalışan bir sunucu bileşenim var. Test etmek istediğimde, birden fazla istek oluşturmak için paralel kitaplık kullanmanın bunu yapacağını düşündüm. Ama bu böyle bitiyor. Görünüşe göre C # 'dan Parallel (Parallel.For) kütüphanesini kullanmak daha kolaydı ama aynı anda her şeyi paralel olarak oluşturuyor gibi görünmüyor. Yani saniyede N isteği oluşturmanın tanımı olamaz. Bunu nasıl yapmalıyım? Önce yük testi yapmak isteyen herkesin bunu düşüneceğini tahmin ediyorum.

  1. Gerçekten saniyede N istek oluşturmanın etkili yolu nedir?

  2. Başka bir efsane paralel programlama ile ilgilidir. Genel olarak C # veya .Net'te paralel programlama desenleri kullandıysanız lütfen bizi aydınlatın. 5 sürecim olduğunu hayal edin. Beş sürecin hepsini aynı anda nasıl başlatacak? Kaynak tüketimim için ne anlama geliyor? İnternet üzerinden ulaşılabilen materyallerin çoğunu okumaya çalıştım ama sorularıma verilen cevaptan daha fazla soru alıyorum.

  3. Parallel.For kullandım ve N iş parçacıkları ve ölçülen zaman yarattım. Sonra görevlerin numaralandırılması için Task.Factory.start kullanarak aynı şeyi denedim. Ölçülen süre farklıydı. Bunları kullanmak arasındaki fark tam olarak nedir? İlgili sınıfları ne zaman ve tam olarak hangi amaçlar için kullanmalıyım? sık sık birçok zenginliğimiz var ama sadece birini diğerinden nasıl ayırt edeceğimizi tam olarak bilmiyoruz. Bu benim için böyle bir durum, neden birini diğerinden kullanmamam gerektiğini bulamamak.

  4. En iyi olduğunu iddia eden bu zamanları ölçmek için kronometre sınıfını kullandım. Bir bileşeni yük testi senaryosunda, yanıt süresini ölçmenin yolu ne olurdu. Kronometre benim için en iyi çözüm gibi görünüyor. Herhangi bir görüş bekliyoruz.

ps: Web uygulamaları için birçok yük testi aracı vardır. Mine, sunucu bileşenlerinin özelleştirilmiş bir örneğidir. Ve sorum daha çok saniyede N iş parçacığı oluşturmakla ilgili.

Tüm görüşlerinizi bekliyoruz. Sadece bir programlama sorusu değil. Tabii ki öyle. Ürününün performansını ilk önce kendi başına QE şeyler yapmak isteyen herhangi bir programcı için çanlar çalmalı, birçok seçeneği denedim ve sonra nasıl yapmalıyım?


SSS, belirli bir programlama problemiyle ilgili olup olmadığını ve programlama mesleğinde pratik bir cevaplanabilir sorun olup olmadığını sorabilir. şüpheci olan ve bunu işaretleyen insanlar. lütfen yorum yap.
Kral

"Aynı anda" ile ne demek istiyorsun? Bunu başarmak için herhangi bir şekilde TPL veya PLinq'i zorlayıp zorlayamayacağınızı merak ediyorum.
Gert Arnold

Sorum saniyede N istekleri üretmektir. Bu senaryoda aynı an, paralel kullanımı iplikleri paralel bir şekilde kullanmaya başlamamı kastediyordu.
Kral

Herhangi bir ardışık analiz yaptınız mı?

3
Programlama ile ilgili olabilir, ancak yayında çok fazla soru var (en az 4). Çok geniş olduğu için kapanmadan önce sormak istediğiniz tek soruya indirgeyeceğim. Az önce bahsettiğiniz 10000 gibi test makinenizdeki çekirdek sayısı gibi ilgili bilgileri verin). Kod gösterilmesi genellikle yardımcı olur.
Gert Arnold

Yanıtlar:


10

Bütün cevaplar bende yok. Umarım üzerine biraz ışık tutabilirim .

.NET'in iş parçacığı modelleri hakkındaki önceki ifadelerimi basitleştirmek için Paralel Kitaplığın Görevleri ve Görevler için varsayılan TaskScheduler öğesinin ThreadPool'u kullandığını bilmeniz yeterlidir. Hiyerarşide ne kadar yüksek olursanız (ThreadPool en alttadır), öğeleri oluştururken daha fazla yükünüz olur. Bu ek yük kesinlikle daha yavaş olduğu anlamına gelmez, ancak orada olduğunu bilmek güzel. Sonuçta algoritmanızın çok iş parçacıklı bir ortamda performansı, tasarımına gelir. Ne performans gösterir sıralı olabilir paralel olarak aynı düzeyde performans. Size sert ve hızlı kurallar vermek için çok fazla faktör var, bunlar ne yapmaya çalıştığınıza bağlı olarak değişir. Ağ istekleriyle uğraştığınızdan, küçük bir örnek vermeye çalışacağım.

Soketler konusunda uzman olmadığımı ve Zeroc-Ice hakkında hiçbir şey bilmediğimi söyleyeyim. Eşzamansız işlemler hakkında biraz bilgim var ve burası size gerçekten yardımcı olacak. Bir soket aracılığıyla eşzamanlı bir istek gönderirseniz, aradığınızda Socket.Receive(), bir istek alınana kadar iş parçacığınız engellenir. Bu iyi değil. İleti diziniz engellendiği için başka istekte bulunamaz. Socket.Beginxxxxxx () kullanarak, G / Ç isteği yapılır ve soket için IRP kuyruğuna konur ve iş parçacığınız devam eder. Bu, iş parçacığınızın aslında herhangi bir engelleme olmadan bir döngüde binlerce istekte bulunabileceği anlamına gelir!

Sizi doğru anlıyorsam, test kodunuzda Zeroc-Ice üzerinden çağrıları kullanıyorsunuz, aslında bir http uç noktasına ulaşmaya çalışmıyorsunuz. Eğer durum buysa, Zeroc-Ice'ın nasıl çalıştığını bilmediğimi itiraf edebilirim. Bununla birlikte, burada listelenen tavsiyeleri , özellikle kısmı takip etmenizi öneririm Consider Asynchronous Method Invocation (AMI). Sayfa şunu gösterir:

AMI kullanarak istemci, çağırma gönderilir gönderilmez (veya hemen gönderilemezse sıraya alınır), denetimin iş parçacığını yeniden kazanır ve bu da müşterinin bu iş parçacığını diğer faydalı işleri gerçekleştirmek için kullanmasına olanak tanır .

Hangi yukarıda .NET yuvaları kullanarak tarif eşdeğer gibi görünüyor. Çok sayıda gönderme yapmaya çalışırken performansı artırmanın başka yolları olabilir, ancak buradan veya o sayfada listelenen başka bir öneriyle başlayacağım. Başvurunuzun tasarımı konusunda çok belirsiz davrandınız, bu yüzden yukarıda olduğumdan daha spesifik olabilirim. Unutmayın, ihtiyacınız olanı elde etmek için kesinlikle gerekli olandan daha fazla iş parçacığı kullanmayın , aksi takdirde uygulamanızın istediğinizden çok daha yavaş çalıştığını görürsünüz.

Sözde koddaki bazı örnekler (gerçekten öğrenmek zorunda kalmadan buza mümkün olduğunca yakın yapmaya çalıştım):

var iterations = 100000;
for (int i = 0; i < iterations; i++)
{
    // The thread blocks here waiting for the response.
    // That slows down your loop and you're just wasting
    // CPU cycles that could instead be sending/receiving more objects
    MyObjectPrx obj = iceComm.stringToProxy("whateverissupposedtogohere");
    obj.DoStuff();
}

En iyi yol:

public interface MyObjectPrx : Ice.ObjectPrx
{
    Ice.AsyncResult GetObject(int obj, Ice.AsyncCallback cb, object cookie);
    // other functions
}

public static void Finished(Ice.AsyncResult result)
{
    MyObjectPrx obj = (MyObjectPrx)result.GetProxy();
    obj.DoStuff();
}

static void Main(string[] args)
{
    // threaded code...
    var iterations = 100000;
    for (int i = 0; i < iterations; i++)
    {
        int num = //whatever
        MyObjectPrx prx = //whatever
        Ice.AsyncCallback cb = new Ice.AsyncCallback(Finished);
        // This function immediately gets called, and the loop continues
        // it doesn't wait for a response, it just continually sends out socket
        // requests as fast as your CPU can handle them.  The response from the
        // server will be handled in the callback function when the request
        // completes.  Hopefully you can see how this is much faster when 
        // sending sockets.  If your server does not use an Async model 
        // like this, however, it's quite possible that your server won't 
        // be able to handle the requests
        prx.GetObject(num, cb, null);
    }
}

Daha fazla iş parçacığı! = Yuva göndermeye çalışırken (veya gerçekten herhangi bir şey yaparken) daha iyi performans olduğunu unutmayın. İş parçacıkları, üzerinde çalıştığınız sorunları otomatik olarak çözecekleri için sihir değildir. İdeal olarak, bir iplik zamanının çoğunu beklemediği sürece çekirdek başına 1 iplik istersiniz, o zaman daha fazlasına sahip olmanızı haklı çıkarabilirsiniz. Bağlam anahtarları ve kaynak israfı olacağından, her isteği kendi iş parçacığında yürütmek kötü bir fikirdir. (Bu konuda yazdığım her şeyi görmek istiyorsanız, düzenle'yi tıklayın ve bu yazının geçmiş revizyonlarına bakın. Yalnızca ana sorunu bulduğu için kaldırdım.)

Saniyede çok sayıda istek yapmak istiyorsanız, bu isteği kesinlikle iş parçacıklarında yapabilirsiniz. Ancak, iş parçacığı oluşturma ile aşırıya kaçmayın. Bir denge bulun ve ona bağlı kalın. Eşzamanlı olmayan bir modelle eşzamanlı bir model kullanırsanız daha iyi performans elde edersiniz.

Umarım bu yardımcı olur.


Performanstan neden bu kadar çok bahsediyorsun? OP'nin istediği gibi görünmüyor.
Ocak'ta svick

1
ops orijinal gönderisinin orijinal olarak 4 sorusu vardı ve paralel vs görevlerin performansı hakkında sorular sordular, sonra düzenlendi ve şimdi geri döndüler. Böylece, okuduklarınızın çoğu bunun bir sonucuydu. Sonuçta, sorusu performansla ilgili olsa da, genel fikri doğru olduğu için, ancak görünüşe göre uygulamasında eksik. Ben son cevap benim sivri cevaplar o soru inanmak vermedi dışarı düzenleyin.
Christopher Currens

1
Sorularımı azaltmak zorunda kaldım çünkü kapatmak için oy vermek istediler. Şimdi öyle görünüyor ki, burada sahip olmak geçerli. @ChristopherCurrens Görevler için threadpool ile fark için +1 iyi bir nokta. Bu benim anlayışımı genişletti. Ama hala saniyede bazı N istekleri oluşturmak gerçekten mümkün mü? Bunu yapmanın en iyi yolu tam olarak nedir?
Kral

@King - Sanırım sandığım kadar net değildim. Son 3-4 paragraf size yardımcı olacağını düşündüm. Zaten bir çeşit döngü kullandığınızı varsaymıştım. Bunu yapıyorsanız, sorun soketinizin gönderdiği / aldıkları durumun engellenmesi ve böylece isteklerinizi yavaşlatmasıdır. Belki bir örnek sahte kod göndermek için biraz zaman bulurum.
Christopher Currens

Onları gerçekten ICE üzerinden göndermede sorunum yok. Sorun aslında N istekleri yaratacak uygulamayı tanımlayan şeydir ve bu sayı N için doğru söylenebilecek bir şeydir.
Kral

2

1. soruya atlayacağım ve # 2'ye gireceğim, çünkü bu genellikle aradığınızı başarmanın kabul edilebilir bir yoludur. Geçmişte saniyede n ileti elde etmek için , daha sonra p AppDomains'i başlatacak tek bir işlem oluşturabilirsiniz . Her bir AppDomain temelde sadece belirli bir zaman noktasına ulaşıldığında (Zamanlayıcı kullanarak) bir istek döngüsü çalıştırmaya başlar. Bu süre, sunucunuza aynı anda vurmaya başladıklarından emin olmak için her bir Uygulama Alanı için aynı olmalıdır.

Bunun gibi bir şey, isteklerinizi göndermek için çalışmalıdır:

WaitCallback del = state => 
{ 
    ManualResetEvent[] resetEvents = new ManualResetEvent[10000]; 
    WebClient[] clients = new WebClient[10000]; 

    for (int index = 0; index < 10000; index++) 
    { 
        resetEvents[index] = new ManualResetEvent(false); 
        clients[index] = new WebClient(); 

        clients[index].OpenReadCompleted += new OpenReadCompletedEventHandler (client_OpenReadCompleted); 

        clients[index].OpenReadAsync(new Uri(@"<REQUESTURL>"), resetEvents[index]); 
    } 

    bool succeeded = ManualResetEvent.WaitAll(resetEvents, 10000); 
    Complete(succeeded); 

    for (int index = 0; index < 10000; index++) 
    { 
        resetEvents[index].Dispose(); 
        clients[index].Dispose(); 
    } 
}; 

while(running)
{
    ThreadPool.QueueUserWorkItem(del);
    Thread.Sleep(1000);
}

Bu, muhtemelen hangi makinede çalıştırırsanız çalıştırabilirsiniz, böylece kaynaklarınız varsa (uygulama etki alanları yerine işlemleri kullanarak) her zaman birkaç farklı makineden benzer bir döngü uygulayabilirsiniz.

Üçüncü sorunuz için bu bağlantıya bir http://www.albahari.com/threading/ okuyun

Son olarak, sunucunuzdaki hem süreyi hem de benzersiz isabetleri izlemek için bir kronometre isabet sayacıyla eşleştirilmelidir. Bu, olaydan sonra biraz analiz yapmanıza izin vermelidir.


2
Burada ayrı AppDomains oluşturmak için olası nedenleriniz nelerdir? Bu tamamen gereksiz görünüyor.
svick

0

N makul derecede küçükse dişlerle uğraşmayın. Saniyede N isteği oluşturmak için duvar saati saatini ( DateTime.Now) kullanın. İsteğin öncesinde ve sonrasında zaman ayırın, ardından bir Sleepsonraki isteği geciktirmek için

Örneğin, N = 5 (200 ms) ile:

Before request: 12:33:05.014
After request: 12:33:05.077
Sleep(137)
Before request: 12:33:05.214
After request: 12:33:05.271
Sleep(131)

Bu mükemmel değil; Eğer bulabilirsiniz Sleepkesin değildir. Çalışan sapma sayısını (X'inci isteklerden önce zaman X-1 / N sonra olmalıdır) tutabilir ve Uyku süresini buna göre ayarlayabilirsiniz.

N çok büyük hale geldiğinde, sadece M iş parçacıkları oluşturur ve her iş parçacığının aynı şekilde N / M istekleri oluşturmasına izin verirsiniz.


Çok fazla sayıda istek oluşturmam gerekiyor. Bu seçenek olamaz çünkü 100 iş parçacıktan önce bile hafızamı (4GB RAM) içecektir.
King

250K kodda tek bir iş parçacığından saniyede 20.000 istek oluşturdum. Zaten 100 iş parçacığı çalıştırmak için yeterli CPU'nuz yok (bu makine sınıfı 4GB ile gelmiyor). Bir sonraki sorun, tüm bu talepleri geri çekmek olacaktır; yük oluşturucunuz ve sunucunuz arasında 10 Gbit / sn Ethernet var mı? Dolayısıyla, gerçek gereksinimlerinizi kontrol etmek isteyebilirsiniz.
MSalters

Açıklığa kavuşturmak için 20+ Gbps gibi bir şeyim var. Yani bu bir sorun değil. Makine sınıfı hakkında, Ne demek istersiniz? işlemci sayısı?
Kral

@King: 100 ipliği itmek için 48 çekirdekli bir makine beklerdim. SGI, örneğin bu kadar çok çekirdekli makineler satıyor, ancak genellikle 32GB veya daha fazla olanlara sahip olacaksınız.
MSalters

0

Herhangi bir .NET projesi için yük testi yapmanın en kolay yolu, Visual Studio'nun Ultimate sürümünü satın almaktır. Bu, yük testleri dahil her türlü testin önceden yapılmasına yardımcı olan entegre bir test aracı ile birlikte gelir. Yük testleri, tek bir bilgisayarda sanal kullanıcılar oluşturarak veya daha fazla sayıda kullanıcı için birkaç kullanıcıya dağıtılarak önceden yapılabilir, ayrıca test süresi boyunca ek veri döndürmek için hedef sunuculara yüklenebilen küçük bir program da vardır.

Bu pahalıdır, ancak nihai sürüm birçok özellik ile birlikte gelir, bu yüzden hepsi kullanılmış olsaydı daha makul bir fiyat olurdu.


0

Tamamen X iş parçacıklarının kaynağınıza tam olarak aynı anda vurmasını istiyorsanız, her iş parçacığını geri sayım mandalının arkasına koyabilir ve semafor kontrolleri arasında kısa bir bekleme süresi belirleyebilirsiniz.

C # 'da bir uygulama vardır (http://msdn.microsoft.com/en-us/library/system.threading.countdownevent(VS.100).aspx).

Aynı zamanda, sisteminizi stres testi yapıyorsanız, aslında yarış koşullarını da kontrol etmek isteyebilirsiniz, bu durumda rasgele frekans ve tepe noktaları / furloughs ile zamanla salınan her iplik üzerinde iplik uyku dönemleri ayarlamak isteyebilirsiniz.

Benzer şekilde, aslında hızlı bir şekilde birden fazla istek göndermek istemeyebilirsiniz, iletilerinizi geri alıp göndermek için daha fazla zaman harcayan daha az sayıda iş parçacığı kurarak sunucunuzu kötü duruma getirme / gerçek dünya performansını test etme konusunda daha iyi bir başarı elde edebilirsiniz. Sunucunuzun yavaş devam eden iletileri işlemek için kendi iş parçacıklarını döndürmesi gerekeceğinden, soket üzerinde ilerleyin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.