2011-08-02 230 views
1

我使用HttpListener作爲簡單的http服務器。我已經通過讓HttpListener爲每個請求返回字符串「OK」來對req/sec性能進行基準測試 - 這已達到每秒16,000個請求的限制。根據以下代碼,我可以做些什麼來進一步優化性能?或者我們是否達到了Windows Http.sys的限制?HttpListener性能優化

圖片上傳不工作,這裏有一個鏈接到Visual Studio性能跟蹤:

VS Performance Trace

Public Class HTTPServer 

    Shared Listener As HttpListener = New HttpListener 

    Public Shared Sub Start() 

     ServicePointManager.DefaultConnectionLimit = 500 
     ServicePointManager.Expect100Continue = False 
     ServicePointManager.MaxServicePoints = 500 

     Listener.Prefixes.Add("http://localhost/") 
     Listener.Start() 

     For i As Integer = 1 To (System.Environment.ProcessorCount * 2) 

      Dim NewThread As New System.Threading.Thread(AddressOf ListenerThread) 
      NewThread.Priority = ThreadPriority.Normal 
      NewThread.IsBackground = True 
      NewThread.Start() 

     Next 

    End Sub 



    Private Shared Sub ListenerThread() 

     Dim SyncResult As IAsyncResult 

     While True 

      SyncResult = Listener.BeginGetContext(New AsyncCallback(AddressOf ListenerCallback), Listener) 
      SyncResult.AsyncWaitHandle.WaitOne() 

     End While 

    End Sub 



    Private Shared Sub ListenerCallback(ByVal StateObject As IAsyncResult) 

     Dim Listener As HttpListener = DirectCast(StateObject.AsyncState, HttpListener) 

     Dim Context As HttpListenerContext = Listener.EndGetContext(StateObject) 
     Dim Request As HttpListenerRequest = Context.Request 

     Dim Response As HttpListenerResponse = Context.Response 

     Dim ResponseString As String = "OK" 

     Dim Buffer As Byte() = System.Text.Encoding.UTF8.GetBytes(ResponseString) 
     Response.ContentLength64 = Buffer.Length 
     Dim OutputStream As System.IO.Stream = Response.OutputStream 
     OutputStream.Write(Buffer, 0, Buffer.Length) 

     OutputStream.Close() 
     OutputStream.Dispose() 

    End Sub 

End Class 
+0

對不起,你是怎麼得到每秒16K的請求?我用300個並行請求進行了測試,每40秒獲得30K個請求。並且使用1-500個代理對Pylot進行壓力測試,並且每秒獲得約250個請求。請解釋它;)我在同一臺機器上進行的所有測試(本地主機)。我做錯了什麼?謝謝!!! – Edward83

+0

P.S.從一個線程(只有一個並行線程)我提出了16K個請求,並且完成了約54秒;我不明白:))) – Edward83

+0

現在我每2-4秒約13-16K個請求)))據我瞭解,我的第一個測試很慢,因爲增量鎖定,跟蹤文件等;我刪除所有這些「垃圾」:) – Edward83

回答

1

一個件事你可以做的僅僅是調用Encoding.UTF8.GetBytes("OK")一次,而不是在每一個請求。我懷疑它會產生多大的影響,但如果你對每個請求都做了完全相同的事情,那麼你最好還是以你需要的形式做出迴應。

我還會使用Using語句,而不是顯式調用Close和Dispose。這不是一個表現的事情 - 只是一般的良好做法,以避免在有異常情況下未封閉流的問題。

實際上,你是否需要才能達到超過16K QPS?你有沒有計算出你是CPU限制還是IO限制?只要你的程序需要真正爲每個請求做一些真正的工作,我會想象這會使你在這裏所做的任何微觀優化變得相形見拙。

+0

感謝您的偉大答案喬恩。我的問題應該更清楚 - 「OK」字符串僅用於對該代碼塊進行基準測試,該字符串將在生產中動態生成。 我正在從哈希表中提取內存中的對象 - 沒有太多的處理正在進行 - 所以http.sys的開銷可能很大。通過這個基準測試,四核處理器的CPU佔用率達到50%左右。 – Satellite

+0

@衛星:沒錯 - 大概是動態生成這些文本需要一些工作......你知道爲了處理請求需要做多少工作嗎?我希望你絕大多數的時間去做「真正的工作」,這使得IIS的開銷大多無關緊要。 –

+0

喬恩,對不起,我提前發佈了我最後的表揚 - 請看修正案。 – Satellite