Search code examples
vb.netiishttplistener

HttpListener Performance Optimization


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:

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

Solution

  • 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.