Ich habe nicht alle Antworten. Hoffentlich kann ich etwas Licht ins Dunkel bringen.
Um meine vorherigen Aussagen zu .NETs Threading-Modellen zu vereinfachen, müssen Sie lediglich wissen, dass die Parallel Library Tasks verwendet und der standardmäßige TaskScheduler für Tasks den ThreadPool verwendet. Je höher Ihre Position in der Hierarchie ist (ThreadPool befindet sich unten), desto mehr Aufwand haben Sie beim Erstellen der Elemente. Dieser zusätzliche Aufwand bedeutet sicherlich nicht, dass er langsamer ist, aber es ist gut zu wissen, dass er vorhanden ist. Letztendlich hängt die Leistung Ihres Algorithmus in einer Umgebung mit mehreren Threads von seinem Design ab. Was sequentiell gut abschneidet, läuft möglicherweise nicht so gut parallel. Es sind zu viele Faktoren involviert, um Ihnen feste und schnelle Regeln zu geben. Sie ändern sich je nachdem, was Sie tun möchten. Da Sie sich mit Netzwerkanforderungen befassen, werde ich versuchen, ein kleines Beispiel zu geben.
Lassen Sie mich feststellen, dass ich kein Experte für Steckdosen bin und so gut wie nichts über Zeroc-Ice weiß. Ich weiß ein bisschen über asynchrone Operationen Bescheid, und hier wird es Ihnen wirklich helfen. Wenn Sie eine synchrone Anfrage über einen Socket senden Socket.Receive()
, wird Ihr Thread beim Aufruf blockiert, bis eine Anfrage eingeht. Das ist nicht gut. Dein Thread kann keine Anfragen mehr stellen, da er blockiert ist. Mit Socket.Beginxxxxxx () wird die E / A-Anforderung gestellt und in die IRP-Warteschlange für den Socket gestellt, und Ihr Thread wird fortgesetzt. Dies bedeutet, dass Ihr Thread tatsächlich Tausende von Anfragen in einer Schleife stellen kann, ohne dass diese blockiert werden!
Wenn ich Sie richtig verstehe, verwenden Sie Anrufe über Zeroc-Ice in Ihrem Testcode und versuchen nicht, einen http-Endpunkt zu erreichen. In diesem Fall kann ich zugeben, dass ich nicht weiß, wie Zeroc-Ice funktioniert. Ich würde allerdings vorschlagen , im Anschluss an die Beratung hier aufgeführt , insbesondere den Teil: Consider Asynchronous Method Invocation (AMI)
. Die Seite zeigt dies:
Durch die Verwendung von AMI erhält der Client den Steuerthread zurück, sobald der Aufruf gesendet wurde (oder, wenn er nicht sofort gesendet werden kann, in die Warteschlange gestellt wurde), sodass der Client diesen Thread in der Zwischenzeit für andere nützliche Aufgaben verwenden kann .
Das scheint das Äquivalent zu dem zu sein, was ich oben unter Verwendung von .NET-Sockets beschrieben habe. Möglicherweise gibt es andere Möglichkeiten, die Leistung zu verbessern, wenn Sie versuchen, viele Sendevorgänge durchzuführen, aber ich würde hier oder mit einem anderen Vorschlag beginnen, der auf dieser Seite aufgeführt ist. Sie waren in Bezug auf das Design Ihrer Anwendung sehr vage, sodass ich genauer sein kann als oben. Denken Sie daran, verwenden Sie nicht mehr Threads als unbedingt erforderlich , um das zu erledigen, was Sie benötigen. Andernfalls wird Ihre Anwendung wahrscheinlich viel langsamer ausgeführt, als Sie möchten.
Einige Beispiele im Pseudocode (versucht, es so nah wie möglich am Eis zu machen, ohne dass ich es wirklich lernen muss):
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();
}
Ein besserer Weg:
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);
}
}
Denken Sie daran, dass mehr Threads! = Bessere Leistung beim Versuch, Sockets zu senden (oder wirklich etwas zu tun). Threads sind insofern keine Zauberei, als sie automatisch jedes Problem lösen, an dem Sie arbeiten. Idealerweise möchten Sie 1 Thread pro Kern, wenn ein Thread nicht viel Zeit damit verbringt, zu warten, dann können Sie mehr rechtfertigen. Das Ausführen jeder Anforderung in einem eigenen Thread ist eine schlechte Idee, da Kontextwechsel auftreten und Ressourcen verschwendet werden. (Wenn Sie alles sehen möchten, was ich darüber geschrieben habe, klicken Sie auf Bearbeiten und sehen Sie sich die früheren Überarbeitungen dieses Beitrags an. Ich habe ihn entfernt, da er nur das Hauptproblem zu trüben schien.)
Sie können diese Anfrage definitiv in Threads stellen, wenn Sie eine große Anzahl von Anfragen pro Sekunde stellen möchten. Gehen Sie jedoch bei der Thread-Erstellung nicht über Bord. Finde ein Gleichgewicht und bleibe dabei. Sie erzielen eine bessere Leistung, wenn Sie ein asynchrones Modell im Vergleich zu einem synchronen Modell verwenden.
Ich hoffe das hilft.