Vb.net HttpListener性能优化

Vb.net HttpListener性能优化,vb.net,iis,httplistener,Vb.net,Iis,Httplistener,我将HttpListener用作一个简单的http服务器。我已经通过让HttpListener向每个请求返回字符串“OK”来测试req/sec性能——这已经达到每秒16000个请求的限制。基于以下代码,我可以做些什么来进一步优化性能?还是说我们达到了Windows Http.sys的极限 图像上载不起作用,以下是指向Visual Studio性能跟踪的链接: 您可以做的一件事是只调用Encoding.UTF8.GetBytes(“OK”)一次,而不是每次请求都调用。我怀疑这会有多大的不同,但是

我将HttpListener用作一个简单的http服务器。我已经通过让HttpListener向每个请求返回字符串“OK”来测试req/sec性能——这已经达到每秒16000个请求的限制。基于以下代码,我可以做些什么来进一步优化性能?还是说我们达到了Windows Http.sys的极限

图像上载不起作用,以下是指向Visual Studio性能跟踪的链接:

您可以做的一件事是只调用
Encoding.UTF8.GetBytes(“OK”)
一次,而不是每次请求都调用。我怀疑这会有多大的不同,但是如果你对每个请求都做完全相同的事情,那么你最好以你需要的形式得到响应

我还将使用
Using
语句,而不是显式调用Close和Dispose。这不是性能问题——只是一般的良好实践,以避免出现异常时未关闭流的问题

实际上,您需要达到16K以上的QPS吗?你有没有弄清楚自己是CPU受限还是IO受限?只要你的程序需要对每个请求做一些实际的工作,我想这会让你在这里做的任何微优化都相形见绌。

你可以做的一件事就是只调用
Encoding.UTF8.GetBytes(“OK”)
一次,而不是每次请求都调用。我怀疑这会有多大的不同,但是如果你对每个请求都做完全相同的事情,那么你最好以你需要的形式得到响应

我还将使用
Using
语句,而不是显式调用Close和Dispose。这不是性能问题——只是一般的良好实践,以避免出现异常时未关闭流的问题


实际上,您需要达到16K以上的QPS吗?你有没有弄清楚自己是CPU受限还是IO受限?一旦您的程序需要对每个请求进行实际操作,我想这将使您在这里进行的任何微优化都相形见绌。

谢谢Jon的精彩回答。在我的问题中,我应该更清楚,“OK”字符串仅用于对这段代码进行基准测试,该字符串将在生产中动态生成。我是在内存不足的情况下从哈希表中提供对象的,处理过程不多,因此http.sys开销可能很大。通过这个基准测试,CPU在四个内核中占50%左右。@Satellite:对-所以动态生成文本可能需要一些工作。。。您是否知道与服务请求所需的工作量相比,将需要多少工作量?我希望你的大部分时间都花在“真正的工作”上,使IIS的开销变得无关紧要。乔恩,很抱歉我过早地发布了我的上一个推荐信-请参阅修正案。@Satellite:好的。。。那么,您可以按照我建议的对字符串进行预编码的方式预序列化对象吗?您使用的是哪种序列化?这可能比你想象的要花费更多的工作。您实际提供了多少QP,并且您确定尝试放大比尝试缩小更有效吗?内存中的对象主要是字符串,因此我可以对其中的/部分/进行预编码,但是大多数确实要求在每次请求时更新时间戳。我使用它有点像使用memcached——作为服务于多个web服务器的web应用程序的中间层。我不期望memcached的性能级别,只是尝试尽我所能进行优化。听起来我还没有对代码做出任何明显的性能“不”的承诺——这才是我一直在寻找的答案!谢谢你的回答,乔恩。在我的问题中,我应该更清楚,“OK”字符串仅用于对这段代码进行基准测试,该字符串将在生产中动态生成。我是在内存不足的情况下从哈希表中提供对象的,处理过程不多,因此http.sys开销可能很大。通过这个基准测试,CPU在四个内核中占50%左右。@Satellite:对-所以动态生成文本可能需要一些工作。。。您是否知道与服务请求所需的工作量相比,将需要多少工作量?我希望你的大部分时间都花在“真正的工作”上,使IIS的开销变得无关紧要。乔恩,很抱歉我过早地发布了我的上一个推荐信-请参阅修正案。@Satellite:好的。。。那么,您可以按照我建议的对字符串进行预编码的方式预序列化对象吗?您使用的是哪种序列化?这可能比你想象的要花费更多的工作。您实际提供了多少QP,并且您确定尝试放大比尝试缩小更有效吗?内存中的对象主要是字符串,因此我可以对其中的/部分/进行预编码,但是大多数确实要求在每次请求时更新时间戳。我使用它有点像使用memcached——作为服务于多个web服务器的web应用程序的中间层。我不期望memcached的性能级别,只是尝试尽我所能进行优化。听起来我还没有对代码做出任何明显的性能“不”的承诺——这才是我一直在寻找的答案!对不起,你是如何每秒收到16K请求的?我用300个并行请求进行测试,每40秒得到30K个请求。并使用1-500种药剂对Pylot进行压力测试,每秒获得250个请求。请解释一下;)我在同一台机器(localhost)上进行的所有测试。我做错了什么?非常感谢。另外,我从一个线程(只有一个并行线程)发出16K请求,并在大约54秒的时间内完成;我不明白:))现在我每2-4秒收到约13-16K个请求。))据我所知,我的第一次测试很慢,因为增量锁定、文件跟踪等;我删除了所有这些“垃圾”:(对不起,你是如何每秒收到16K请求的?我对300个并行请求进行了测试,每40个请求中有30K个请求
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