背景
我正在比较在 IIS 7 下运行的 NancyFx 和 ServiceStack.NET 的性能(在 Windows 7 主机上测试)。两者都非常快——在本地测试每个框架处理超过 10,000 多个请求/秒,ServiceStack 快约 20%。
我遇到的问题是 ASP.NET 似乎正在缓存来自 HttpHandler 的每个唯一 URI 请求的响应,迅速导致巨大的内存压力(3+ GB)和垃圾收集器过度工作(大约 25% 的时间消耗GC)。到目前为止,我一直无法禁用对象的缓存和构建,并且正在寻找有关如何禁用此行为的建议。
细节
请求循环基本如下:
for i = 1..100000:
string uri = http://localhost/users/{i}
Http.Get(uri)
响应是一个简单的 JSON 对象,格式为 { UserID: n }。
我已经破解了打开的 WinDBG,每个请求都有:
- 一
System.Web.FileChangeEventHandler
- 二
System.Web.Configuration.MapPathCacheInfos
- 二
System.Web.CachedPathDatas
- 三
System.Web.Caching.CacheDependencys
- 五
System.Web.Caching.CacheEntrys
显然,这些缓存项让我相信这是一个缓存膨胀问题(我很想摆脱 150,000 个不可用的对象!)。
到目前为止我尝试过的
- 在 IIS 'HTTP Resonse Headers' 中,将 'Expire Web content' 设置为 'immediately'。
在 web.config
<system.web> <caching> <outputCache enableOutputCache="false" enableFragmentCache="false"/> </caching> </system.web>
也在 web.config 中(以及策略的许多变体,包括没有)。
<caching enabled="false" enableKernelCache="false"> <profiles> <add policy="DontCache" kernelCachePolicy="DontCache" extension="*/> </profiles> </caching>
查看框架的源代码,看看是否有任何内置的“功能”会使用 ASP.NET 缓存。虽然有缓存帮助器,但它们是框架本身私有的,并且似乎没有利用 ASP.NET 缓存。
更新#1
通过反射器挖掘我发现将值设置UrlMetadataSlidingExpiration
为零可以消除大部分过多的内存使用,但代价是吞吐量减少了 50%(FileAuthorizationModule 类缓存 FileSecurityDescriptors,当UrlMetadataSlidingExpiration
是非零)。
这是通过更新 web.config 并将以下内容放入:
<hostingEnvironment urlMetadataSlidingExpiration="00:00:00"/>
如果可能,我将尝试完全禁用 FileAuthorizationModule 运行,看看是否有帮助。但是,ASP.NET 仍在生成 2*NMapPathCacheInfo
和CacheEntry
对象,因此内存仍在消耗,只是速度要慢得多。
更新#2
问题的另一半与此处描述的问题相同:防止许多不同的 MVC URL 填充 ASP.NET Cache。环境
<cache percentagePhysicalMemoryUsedLimit="1" privateBytesPollTime="00:00:01"/>
有帮助,但即使使用这些非常激进的设置,内存使用量也会迅速上升到 2.5GB(与 4GB 相比)。理想情况下,这些对象一开始就不会被创建。如果做不到这一点,我可能会求助于使用反射来清除缓存的 hacky 解决方案(所有这些条目都是“私有的”,并且在迭代公共缓存时不会枚举)。