2017-05-05 2 views
-1

Unten habe ich eine Anwendung, wo ich versuche, so viele Daten wie möglich mit C# Sockets zu senden. 10 Sekunden nach dem Start der Daten stoppe ich den Datenversand und warte auf einen Konsolentaste, wobei ich auch auf die Konsole schreibe, wie viele Anfragen gesendet wurden.Senden von Daten über Sockets ist langsamer mit gleichzeitigen Threads?

Wenn ich die Anzahl der Threads auf 1 einstellte, erreichte ich viel höhere Anfragen. Hier sind die Protokolle

Attempt 1 => 86873 
Attempt 2 => 107324 
Attempt 3 => 97426 
Attempt 4 => 94720 
Attempt 5 => 97927 
Attempt 6 => 94327 
Attempt 7 => 94791 

Wie Sie sehen können, seine Spitze zwischen 80.000 und 110.000 dort etwa. Wenn ich es auf etwas höher als 1 setze (ich habe 1 und 2 versucht), trifft es nicht einmal 80.000 und erreicht in den 10 Sekunden etwa 70-75.000. Meine Gedanken waren mehr Threads = mehr Daten gesendet, da es hinter den Kulissen mehr Arbeit leistet? Kann mir jemand dazu etwas sagen?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace RDOS 
{ 
    public class ThreadHandler 
    { 
     private int count = 0; 
     private int threadCount = 3; 
     private List<Thread> _threads = new List<Thread>(); 

     private string _ip; 
     private int _port; 

     public int RequestsSent; 
     public int RequestsFailed; 
     public DateTime Started; 

     public ThreadHandler() 
     { 
      Console.Write("IP: "); 
      _ip = Console.ReadLine(); 

      Console.Write("Port: "); 
      _port = int.Parse(Console.ReadLine()); 

      Console.WriteLine("sending data to " + _ip + " on port " + _port); 

      Thread backgroundThread = new Thread(new ThreadStart(OnBackgroundThread)); 
      backgroundThread.Start(); 

      for (int i = 0; i < threadCount; i++) 
      { 
       _threads.Add(new Thread(new ThreadStart(OnThread))); 
      } 

      foreach (Thread thread in _threads) 
      { 
       thread.Start(); 
      } 
     } 

     public void OnBackgroundThread() 
     { 
      Started = DateTime.Now; 

      while (true) 
      { 
       System.Threading.Thread.Sleep(10000); 
       TimeSpan span = DateTime.Now - Started; 
       Console.WriteLine("Sent " + RequestsSent + " requests (running for " + span.TotalSeconds + ")"); 
       Console.ReadKey(); 
      } 
     } 

     public void OnThread() 
     { 
      IPEndPoint RHost = new IPEndPoint(IPAddress.Parse(_ip), _port); 

      using (Socket socket = new Socket(RHost.AddressFamily, SocketType.Dgram, ProtocolType.Udp)) 
      { 
       socket.Blocking = true; 

       while (true) 
       { 
        RequestsSent++; 
        byte[] buf = System.Text.Encoding.ASCII.GetBytes("fwkdkskdsksk"); 
        socket.SendTo(buf, SocketFlags.None, RHost); 
       } 
      } 
     } 
    } 
} 
+0

Ich weiß nicht viel über Sockets, aber ich nehme an das könnte ein Problem sein 'socket.Blocking = true;' – TheLethalCoder

+4

Dude, dein Messcode hat einen sehr großen Fehler, 'RequestsSent' muss mindestens als 'volatile' gekennzeichnet sein ', sonst speichert .net den Wert zwischen den Aufrufen, so dass mehrere Threads vorherige Werte sehen und der Zähler nicht wie erwartet funktioniert. Selbst bei volatilen Werten werden einige Werte nicht erkannt, daher sollte der Wert vor der Aktualisierung besser gesperrt werden. – Gusman

+0

Das Schreiben in 'Console' bewirkt auch, dass sich die Threads synchronisieren. [Siehe hier] (https://stackoverflow.com/questions/29960436/why-is-my-multi-threading-slower-than-my-single-threading) – Amy

Antwort

6

Neben the thread safety error which is causing you to get lower than actual numbers, während Sie mehrere Threads haben aber immer noch nur einen Netzwerkadapter haben, dass wahrscheinlich ist, wo Ihr Engpass ist.

Werfen mehr CPU-Leistung bei einem I/O Bindung Problem erhält Sie nicht schneller I/O, in der Tat der meisten Zeit werden dazu führen, dass Sie langsamer I/O haben aufgrund des über Kopf aus der Verriegelung der OS eingeführt muss tun, um den Zugriff auf das I/O-Gerät zu serialisieren. Der einzige Weg, um schneller I/O zu bekommen, ist schnellere Hardware zu bekommen.

+0

Wäre ich besser dran, wenn ich nur 1 Thread lief? Wie würde ich den Thread-Sicherheitsfehler beheben und die ganze Thread-Methode sperren? –

+1

Ersetzen Sie 'RequestsSent ++;' durch 'Interlocked.Increment (ref RequestsSent);', um den Thread-Sicherheitsfehler zu beheben. Was das Threading betrifft, würde ich mit 1 anfangen und dann langsam nach oben gehen und die Rate messen und sehen, wo der Sweet Spot ist. –

Verwandte Themen