【问题标题】:HttpListener Performance OptimizationHttpListener 性能优化
【发布时间】:2011-10-17 23:33:17
【问题描述】:

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

图片上传不工作,这里是 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

【问题讨论】:

  • 对不起,你是怎么得到每秒 16K 的请求的?我用 300 个并行请求进行了测试,每 40 秒收到 30K 个请求。并使用 Pylot 对 1-500 个代理进行压力测试,每秒收到约 250 个请求。请解释一下;)我在同一台机器(本地主机)上进行的所有测试。我做错了什么?谢谢!!!
  • P.S.我从一个线程(只有一个并行线程)发出 16K 请求,大约 54 秒完成;我不明白:)))
  • 现在我每 2-4 秒收到约 13-16K 请求)))据我所知,由于增量锁定、跟踪文件等,我的第一次测试很慢;我删除了所有这些“垃圾”:)

标签: vb.net iis httplistener


【解决方案1】:

一个你可以做的就是只调用一次Encoding.UTF8.GetBytes("OK"),而不是每次请求。我怀疑它会产生很大的不同,但如果您对每个请求都执行完全相同的操作,那么您最好以您需要的形式获得响应。

我也会使用Using 语句,而不是显式调用 Close 和 Dispose。这不是性能问题 - 只是在出现异常时避免未关闭流出现问题的一般良好做法。

实际上,您需要达到超过 16K QPS 吗?你确定你是受 CPU 限制还是 IO 限制?一旦您的程序需要对每个请求实际执行一些实际工作,我想这将使您在这里所做的任何微优化都相形见绌。

【讨论】:

  • 感谢乔恩的精彩回答。我的问题应该更清楚 - “OK”字符串仅用于对这段代码进行基准测试,该字符串将在生产中动态生成。我正在从内存不足的哈希表中提供对象 - 没有太多的处理正在进行 - 所以 http.sys 开销可能很大。通过这个基准测试,四个核心的 CPU 占用率约为 50%。
  • @Satellite:是的 - 所以动态生成该文本可能需要一些工作......你知道这将是多少工作与仅仅为请求提供服务所需的工作?我期望您的大部分时间都花在“真正的工作”上,这使得 IIS 的开销几乎无关紧要。
  • 乔恩,对不起,我过早地发布了我的最后一个推荐 - 请参阅修正案。
  • @Satellite:好的……那么你能像我建议的预编码字符串一样预序列化对象吗?您使用的是哪种序列化?这很可能比您想象的要花费更多的工作量。您真正服务了多少 QPS,您确定尝试扩大规模比扩大规模更有效吗?
  • 内存中的对象主要是字符串,所以我可以对它们中的/一些/进行预编码,但是大多数确实需要在每次请求时更新时间戳。我使用它有点像使用 memcached - 作为服务于多个 Web 服务器的 Web 应用程序的中间层。我不期望 memcached 的性能水平,只是试图优化我能做的。听起来我没有对代码做出任何明显的表现“不” - 这确实是我正在寻找的答案!
猜你喜欢
  • 2013-03-17
  • 2016-05-14
  • 2014-01-08
  • 1970-01-01
  • 2017-06-02
  • 2013-03-31
  • 2018-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多