HttpListener:写入输出流的速度取决于内容?

Posted

技术标签:

【中文标题】HttpListener:写入输出流的速度取决于内容?【英文标题】:HttpListener : writing to outputstream slow depending on content? 【发布时间】:2013-12-16 23:45:13 【问题描述】:

删除了旧问题并完全重写,因为我已经为此做了很多工作以查明问题。我的问题是我正在使用自定义服务器编写自定义 CMS,以非常非常高的速度/吞吐量作为目标,但是我注意到某些数据或数据模式会导致严重减速(从 0 到 55+ms 响应时间)。我真的需要比我更好的人来帮助解决这个问题,因为我对正在发生的事情一无所知,我怀疑 .net 框架中的一个错误,但我不知道它可能在哪里,小的 .net 代码浏览我确实没有建议输出 Stream 执行任何特定于数据的操作

我已经测试过并且确定不是问题的东西:

内容大小(内容越大速度越快) 内容类型(相同内容类型之间的差异) 大部分周边代码(做了一个极简项目来重现这个bug,大约15行,找到帖子底部的链接,包含重现它的数据,运行它,用2个URL测试,见自己)。 不是网页/缓存等问题,在 Firefox 中使用单个图像和 CTRL+F5 重现问题,删除图像的最后几个字节可以 100% 修复它,重新添加它们会再次导致问题李> 在输出流之外不存在问题(将其替换为目标内存流不会显示问题)

如何重现问题:

下载并运行项目 使用您喜欢的浏览器并转到 localhost:8080/magicnumber 用你想要的替换那个url中的magicnumber,你会收到减去那个字节数的图片

我的结果:

该图像持续 50 毫秒左右 将幻数增加到 1000 根本不会影响这一点 稍远一点(我认为大约 1080 左右?)它突然下降到 0MS 不确定发生了什么,但似乎在 Firefox 中使用 CTRL+F5 时,每个请求至少有 2 个请求,在正确的情况下,两者都是 0ms,在错误的情况下,第一个仍然是 0ms,但另一个变成 50ms,我假设第一个只是检查文件缓存是否正常并且我仍在回答但 Firefox 关闭了连接或其他什么?

非常感谢任何帮助,将我所有的代表都放在 Bounty 那里,因为我真的需要知道我是否沿着这条路走/获取更多信息来报告这一点,或者我是否进入较低级别并执行我自己的 http.sys 互操作(而且,最重要的是,如果该错误仅在 .net 端或更低级别,并且降低级别将无法修复它!)

示例文件是一个 gziped 数组,我的内容在 db 中被预缓存和预压缩,因此这代表了我需要发送的数据。

https://www.dropbox.com/s/ao63d7din939new/***SlowServerBug.zip

编辑:如果我打开了提琴手,有问题的测试会回到 0 毫秒,到目前为止我不知道该怎么做,这意味着我在发送一些数据时会大幅减速,这不是由数据类型而不是实际数据定义,如果我在两者之间有提琴手,则不会发生这种情况。我迷路了!

编辑 2:用另一个浏览器测试只是为了确定,实际上它在 IE 上回到了 0 毫秒,所以我假设它实际上可能不是 HttpListener 错误,而是 Firefox 错误,我将编辑我的问题和标签如果没有人提出其他建议。如果是这种情况,有人知道我应该在哪里查看 FF 的代码以了解问题吗? (这绝对是一个问题,即使在他们这边,因为我再次与 2 个文件进行比较,一个比另一个大,相同的文件格式,最大的总是需要 0 毫秒,最小的总是需要 55 毫秒!)

【问题讨论】:

您的基准测试是针对 Windows 还是 Windows Server? 我都做了,我给出的运行是针对 Windows 8.1,但是我认为单个连接应该没有什么不同。请注意,这不是性能问题(根据服务器和客户端的连接设置可能会有所不同),而是与内容相关的性能问题 编辑:在功能强大的 Windows server 2012 DC 上运行特定测试,这不是决定性的,但总体而言时间要短得多,我需要找到一个更大的复制案例,但我做到了之前看到过类似的东西(在一张接近 200 毫秒的图像上) 如果您安装 Fiddler,您将获得一些可能有助于激发大脑的信息。 如果我这样做了,我会感到惊讶,因为它写入输出流的速度很慢,我不确定提琴手会告诉我什么(这不是下载阶段需要 50 毫秒,而是萤火虫中的“等待”阶段)。这不是我的专业领域,所以如果你有任何建议,如果你能抓住这个项目并运行 fiddler,我会很高兴 【参考方案1】:

两个请求问题:

铬:

第一个请求 = 网站图标 第二个请求 = 图片

火狐:

第一个请求 = 标签的图片 第二个请求 = 图片

更多信息:

http://forums.mozillazine.org/viewtopic.php?t=341179

https://bugzilla.mozilla.org/show_bug.cgi?id=583351

IE:

似乎只发出一个请求

如果你通过提琴手发送请求,你永远不会收到两个。

性能问题:

首先,您的演示应用中的计时器存在问题。每次异步请求处理程序触发时都会重新启动它,这意味着为请求 A 启动的计时器将在收到请求 B 时重新启动,可能在请求 A 完成之前重新启动,因此您将无法获得正确的值。而是在 ContinueWith 回调中创建秒表。

其次,我看不出“幻数”真的会影响性能(除非它导致抛出异常,我猜)。导致性能下降的唯一方法是发出大量并发请求并导致等待锁不断被命中。

总结:我认为HttpListener类没有问题

【讨论】:

你是对的,没有想到它可能是 N+1 而不是 NX2,但是不能将其标记为答案,我只是把它放在那里以防它与问题有关,但它是提供所有信息根本不是问题(因此它在我的结果部分中),但我的问题实际上是“为什么一些数据在没有明显原因的情况下通过输出流非常缓慢。感谢您的提示,但肯定有帮助我的好奇心(只发生在极简主义示例中,因为我没有检查 url,而不是在我的服务器上) 是的,我明白了,我会添加它作为评论,但是信息太多。我现在正在研究问题的另一部分 演示非常简单,正如我所说的那样,它“没有”任何并发查询发生,所以在 A 完成之前没有查询 B 发生,我只需按 CTRL+F5 并等到它完成单个图像,只有少数图像表现出这一点,并且与它们的大小完全无关,magicnumber 没有理由影响性能,这就是为什么这是一个非常疯狂的问题。我认为 HttpListener 不再有问题,一切都指向 Firefox 错误,我(疯狂猜测)认为那些 png 有问题,或者他们的读者在最后一个字节上有问题 而不是下载然后处理Firefox不会释放连接,直到它完成处理它们,所以它“停止”50ms试图找出它们并在那个时候保持连接打开/不'之前没有完成下载。服务器端没有例外,请求全部完成(并且幻数使图像显示正常,但部分显示,只有下载的部分可以)。这也是 Firefox 的运行,根本没有插件。 重要的是要注意性能并没有降低,它是 100% 稳定的,对所有资源(网页、png、JPG、css、js)的每个请求在本地需要 0 毫秒,除了一些图像(实际上比其他需要 0 毫秒的更小),后者需要 50 毫秒左右(总是在 1 毫秒内相同的时间,没有并发请求)。尝试其中一个错误的文件 1000 次,得到 50ms 1000 次,尝试一个好的文件,得到 0 ms 1000 次。零退化

以上是关于HttpListener:写入输出流的速度取决于内容?的主要内容,如果未能解决你的问题,请参考以下文章

Httplistener 中的“指定的网络名称不再可用”

缓冲流

Java第三阶段学习(缓冲流)

替代 HttpListener?

如何在不写入输出流的情况下从 ZipInputStream 获取每个 ZipFile 条目的字节/内容?

为啥HDFS写入速度如此之慢