2016-02-22 10 views
5

Ich bin mir nicht sicher, ob dies eher akka.net oder TPL betrifft, aber ich werde Schauspieler für mein Beispiel verwenden, um die Frage zu klären.Mehrere Threads sofort löschen in akka.net

Die Frage in Kürze: Gibt es eine Möglichkeit, akka.net zu sagen, mehr Threads auf einmal zu feuern, als ich eigentlich CPU-Kerne habe? Hier ist der Beispielcode und die Details:

Ich verwende derzeit einen Laptop mit einem 8-Core-Prozessor. Also lassen Sie uns sagen, dass ich 20 Schauspieler bin zu schaffen:

for (int i = 0; i < 20; i++) 
{ 
    actorList.Add(system.ActorOf<ExampleActor>()); 
} 

Und dann eine Nachricht an alle, die ich vorbei:

actorList[0].Tell(new ExampleMessage()); 
Console.WriteLine("sent message to actor 1\t" + DateTime.Now.TimeOfDay); 
actorList[1].Tell(new ExampleMessage()); 
Console.WriteLine("sent message to actor 2\t" + DateTime.Now.TimeOfDay); 
... 
actorList[19].Tell(new ExampleMessage()); 
Console.WriteLine("sent message to actor 20\t" + DateTime.Now.TimeOfDay); 

der Alle Schauspieler ist, während die Nachricht empfängt, ist die folgende gefälschte lang~~POS=TRUNC-Prozess:

Console.WriteLine("Accessing slow service\t" + DateTime.Now.TimeOfDay 
    + "\t" + Thread.CurrentThread.ManagedThreadId); 
Thread.Sleep(60000); 
Console.WriteLine("Service call was successful\t" + DateTime.Now.TimeOfDay 
    + "\t" + Thread.CurrentThread.ManagedThreadId); 

ich auch diesen Code in seinem Konstruktor haben, so dass ich weiß, wenn der Schauspieler tatsächlich erstellt wird:

public ExampleActor() 
{ 
    Console.WriteLine("Creating " + this.Self.Path + DateTime.Now.TimeOfDay); 
    .... 
} 

So jetzt, wenn ich die Anwendung ausführen, bekomme ich zuerst die "sendete Nachricht an den Aktor" Zeile für alle 20 Akteure - in der gleichen Millisekunde. Aber dann, wenn die Zeit von der Initialisierung kommt, werden zunächst nur 8 Schauspieler erschaffen.

Dann, da keiner der anderen Schauspieler den Job beendet hat, GENAU eine Sekunde später, wird eine andere initialisiert (die neunte). Eine weitere Sekunde später haben wir unseren 10. Schauspieler erstellt und starten den Thread.Sleep-Vorgang.

Jetzt ist die Frage, gibt es eine Möglichkeit, akka.net (oder die TPL darunter) zu sagen, dass ich sicher bin, dass die Threads auf ~ 60 Sekunden für jeden Serviceanruf warten? Damit alle 20 Threads auf einmal abgefeuert werden, statt 8 auf einmal gestartet zu haben, und die vollen 20 Threads, die erst nach 12 Sekunden ausgeführt werden, verstrichen sind?

Antwort

3

Akka-Akteure werden standardmäßig auf dem .Net-ThreadPool ausgeführt.

Sie haben einen ThreadPool-Mangel, bei dem alle verfügbaren Threads ausgelastet sind (einer pro CPU). Wenn alle Threads besetzt sind, fügt der ThreadPool seinem Pool einen weiteren Thread pro Sekunde hinzu.

Um Ihr Problem zu "lösen", könnten Sie die Mindestanzahl der Threads mit ThreadPool.SetMinThreads erhöhen. Aber die wirkliche Lösung besteht darin, Threads nicht zu blockieren (und keine Aktoren zu blockieren).

Wenn Ihre Arbeitslast CPU-gebunden ist, würde es nicht schneller laufen, wenn mehr Akteure gleichzeitig ausgeführt werden.

Wenn Ihre Arbeit ist IO gebunden ist, sollten Sie es asynchron aufrufen:

Receive<string>(msg => 
{ 
    DoSomethingAsync(msg).PipeTo(Self); 
} 

Receive<Result>(msg => 
{ 
    // Process the result 
} 
+0

Danke. Leider möchten einige Clients explizite Thread-Einstellungen, aber für jeden, der dies liest, der nicht an die Anforderungen gebunden ist, schlage ich vor, dass Sie der asynchronen Route folgen. Getestet, alles funktioniert perfekt. – nikovn