I'm using HttpListener as a simple http server. I've been benchmarking req/sec performance by having HttpListener return the string "OK" to each request - this has hit a limit at 16,000 requests per second. Based on the following code, is there anything that I can do to further optimize performance? Or are we hitting the limits of Windows Http.sys?
Image uploading isn't working, here's a link to the Visual Studio 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
Well one thing you can do is only call Encoding.UTF8.GetBytes("OK")
once, instead of on every request. I doubt that it'll make much difference, but if you're doing exactly the same thing on every request, you might as well have that response in the form you need it.
I would also use a Using
statement rather than calling Close and Dispose explicitly. That's not a performance thing - just general good practice to avoid problems with unclosed streams when there are exceptions.
Realistically, do you need to hit more than 16K QPS? Have you worked out whether you're being CPU-bound or IO-bound? As soon as your program needs to actually do some real work on each request, I would imagine that will dwarf any micro-optimizations you make here anyway.