2017-05-05 104 views
-1

下面我有一個應用程序,我試圖發送儘可能多的數據以儘可能快的方式使用C#套接字。數據啓動10秒後,我停止發送數據並等待控制檯密鑰,同時向控制檯寫入發送了多少個請求。併發線程在套接字上發送數據比較慢?

當線程數量設置爲1時,我達到了更高的請求。這裏是日誌

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

正如你可以看到,其峯值在80,000到110,000之間。當它設置爲高於1(我試過1和2)時,它甚至沒有達到8萬,在10秒內達到70-75萬。我的想法是更多的線程=更多的數據發送,因爲它在幕後做更多的工作?任何人都可以給我一些這方面的信息嗎?

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

我不太瞭解套接字,但我認爲這可能是一個問題'socket.Blocking = true;' – TheLethalCoder

+4

老兄,你的測量代碼有一個很大的缺陷,'RequestsSent'必須至少標記爲volatile ',否則.net會緩存調用之間的值,因此多個線程會看到以前的值,因此計數器不能按照您的預期工作。即使使用volatile,它也會丟失一些值,在更新值之前更好地鎖定值。 – Gusman

+0

寫入'Console'還會導致線程同步。 [見這裏](https://stackoverflow.com/questions/29960436/why-is-my-multi-threading-slower-than-my-single-threading) – Amy

回答

6

此外the thread safety error which is causing you to get lower than actual numbers,雖然你可能有多個線程,但你仍然只有一個網絡適配器,也有可能是你的瓶頸。

在I/O界限問題下投擲更多的CPU能量不會讓你的I/O速度更快,實際上大多數情況下,由於鎖定OS導致的開銷會導致I/O速度降低必須做到序列化訪問I/O設備。獲得更快I/O的唯一方法是獲得更快的硬件。

+0

然後我只需要運行1個線程會更好嗎?另外,我將如何解決線程安全錯誤,鎖定整個線程方法? –

+1

用'Interlocked.Increment(ref RequestsSent)'替換'RequestsSent ++;';'修復線程安全錯誤。至於穿線,我會從1開始,然後慢慢上升,測量比率並查看最佳位置。 –