2011-02-10 63 views
2

我正嘗試儘可能多的排擠我的UDP數據收集套接字儘可能使用下面的代碼:高性能UDP服務.NET

public void Start() 
{ 

    if (socket == null) Open(); 
    this.stats.PositionServerStarted = DateTime.Now; 
    this.state = SocketWorkerState.Running; 
    AsyncBeginReceive(); 
} 

private void AsyncBeginReceive() 
{ 
    DataPacket dataPacket = new DataPacket(socket, this.settings.IPAddress, 
     this.settings.Port, SocketWorker.MaxDataRead); 
    Interlocked.Increment(ref stats.ProcessingThreads); 
    socket.BeginReceiveFrom(dataPacket.BytePacket, 0, 
     SocketWorker.MaxDataRead, SocketFlags.None, 
     ref dataPacket.RemoteEndPoint, new AsyncCallback(AsyncEndReceive), 
     dataPacket); 
} 

private void AsyncEndReceive(IAsyncResult ar) 
{ 
    DataPacket dataPacket= null; 
    AsyncBeginReceive(); 
    dataPacket = (DataPacket)ar.AsyncState; 
    dataPacket.EnteredQueue = DateTime.Now; 
    dataPacket.DataLength= dataPacket.SourceSocket.EndReceiveFrom(ar, 
     ref dataPacket.RemoteEndPoint); 
    Interlocked.Decrement(ref stats.ProcessingThreads); 
    Interlocked.Increment(ref this.stats.PacketsQueued); 
    ThreadPool.QueueUserWorkItem(new WaitCallback(OnPacketArrived), 
     dataPacket); 
    Interlocked.Decrement(ref this.stats.PacketsQueued); 
} 

private void OnPacketArrived(object packet) 
{ 
    //go ahead and process the packet 
} 

有沒有人對如何改進這個任何想法?從AsyncEndReceive()撥打AsyncBeginReceive()認爲是最佳做法?

我已經調整了線程池來

ThreadPool.SetMinThreads(20,20); 
ThreadPool.SetMaxThreads(250, 250); 

但如果我說實話這似乎並沒有對性能產生很大的影響。

回答

1

就我個人而言,當您啓動時會發送多個recvs,即調用AsyncBeginReceive()可調整的次數。這樣你就不用等待一個recv完成,然後下一個就可以開始了。在非託管條款中,總是有一個好主意,總是有一個異步讀取掛起,以便I/O子系統可以直接讀入緩衝區 - 這可能會也可能不會轉化爲更高的性能,但很可能轉化爲更少的丟失數據報。

您也可能想要增加套接字的recv緩衝區大小,因爲這也有助於防止丟失的數據報。我懷疑你將不得不調整線程池設置。在非託管代碼中,您可以使用異步I/O處理大約5個左右線程的完全加載的網絡管道;你們中有250人遠離商標。

0

只有當您的工作不夠好時才進行優化,如果您必須進行優化,請根據指標進行優化 - 嘗試不同方法並使用最佳工作方式。

這就是說,我不相信,這種方法是任何不是簡單地在一個循環中,在ReceiveFrom塊然後同步地完成每個數據包的處理Ñ + 1線程,避免了使用兩個異步的I /更有效地O和線程間隊列。將 n設置爲瓶頸設備的數量(通常是處理器內核,但是如果您的I/O數量很大,或者兩者兼有,主軸可能也是您的限制資源); 「+ 1」部分只是爲了避免線程正在做其他事情時在負載下閒置設備。

我在.Net(包括完整和緊湊的框架)中對ThreadPoolBeginXxx的異步I/O都有一些非常痛苦的體驗,因此我通常不推薦使用它們。再一次,很多痛苦(至少來自異步I/O)可能是由於其他人的糟糕代碼造成的; ThreadPool只是在緊湊的框架上不可靠。 :-)

0

我不認爲異步是實現高性能的好方法。手動讀取並在每次傳遞中請求更大的數據塊。如果您的併發連接數量少,您甚至可以將線程專用給它們,因此套接字得到您的充分關注。與直接操作相比,異步操作有很多開銷。

如果您需要真正的高吞吐量,請考慮設置線程優先級。另請注意,.Net優先級僅爲相對值,因此您可能也需要設置process priority

如果您正在查看高吞吐量速度,項目屬性中的優化設置可能會對性能產生顯着影響。

+1

如何從UDP套接字中讀取「更大的塊」,您要麼獲取整個數據報,要麼不是。 – 2011-02-10 17:59:26

+0

更改mtu尺寸? – AnthonyLambert 2011-10-11 12:48:51