将HTTPS用于Web服务或Web请求时的内存使用问题

时间:2012-01-09 23:06:09

标签: c# .net memory https

编辑:在评论中经过长时间的讨论后,似乎我的原始问题并没有真正捕捉到正在发生的事情。这是我现在所处位置的摘要:

  • 当使用HTTPS时,我会考虑在第一个HTTPS请求(Web服务调用,WebClient.DownloadFile(Web服务调用,WebClient.DownloadFile)时,我的应用程序的虚拟内存空间(通常从50mb以下到200mb以下)急剧跳跃。 )等等)
  • 与此同时,CPU内核的使用率也接近100%。这通常只持续几秒钟,但我看到它持续时间更长
  • 很可能这只是使用HTTPS的成本,但我很惊讶,因为我之前从未在其他应用程序中注意到它(我的团队中的其他开发人员从未在此应用程序中注意到它,我很久以前一直在使用HTTPS。
  • 踢球者:这似乎不会发生在所有机器上,但在大多数机器上都会发生。如果它在每台机器上始终如一地发生,我就更愿意接受它作为开展业务的成本。"但是,由于运行相同代码和操作系统的某些机器之间似乎存在差异,我想理解为什么会这样,因为它要么a)允许我们减轻行为,要么b)以满足的方式解释它非技术性高层,它实际上不是一个问题",因为解释说Windows任务管理器显示虚拟内存而不一定是主动使用的物理内存并不令人满意到目前为止:/

如果有人感兴趣的话,我已经完整地留下了原始帖子,但它更多地关注网络服务,而这些服务并不是问题的根源。

提前感谢您的任何进一步见解!


当我们的应用程序首次使用https调用我们的Web服务时,我们会看到内存使用量急剧增加。具体情况因机器而异,但作为一个例子,我们可能会看到我们的应用程序在第一次Web服务调用时从大约50mb跳到250mb以上,并且使用率从未降低。后续调用不会导致另一次这样的跳转。我可以使用下面的代码(不是我们的应用程序特有的)和我们不拥有的公共Web服务重现行为 - 因此它似乎独立于我们的客户端和服务器端代码。

有趣的是,在我的测试应用程序中,我没有观察到Windows XP的这种跳跃(我们的应用程序目前仅在Windows 7上部署)。我们也没有在办公室的每个开发/测试机器上看到它(但我们最常做的),而且我们目前还没有办法从"中的机器中检索这些信息。现实世界。"

我还没能确定分配的内容,但有几位分析人员明确表示它位于本机(非托管)内存中。使用DebugDiag分析一些WinDbg转储让我相信在crypt32.dll中分配的内存很多,但是没有被释放。这在某种程度上是有道理的(https意味着证书,安全性等等,并且很可能无论正在加载的是什么都被缓存,因此后续调用为什么不会导致额外的跳转),但我有很难相信这只是将https用于网络服务的成本。

我知道会有一些来自&#34的回复;如果更高的内存使用率不会导致问题,为什么要担心?"营。一般情况下我同意 - 任务管理器中的内存使用数量通常不表示应用程序是否按预期工作。如果应用程序严格在内部使用,只要它不是其他问题的症状,我就可以忍受。但我们的应用程序部署在消费者机器上,所以我们不得不担心问题的感知和实际问题一样多。所以,如果有任何方法可以解决这个问题,我将非常感激!

最后,我在下面的测试代码中使用的Web服务可以在这里找到:http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx?wsdl。 EmailVerNoTestEmail的代码是使用wsdl.exe工具生成的,略微修改了将URL作为参数传递给构造函数而不是对其进行硬编码(以便可以动态指定http / https)。

public static void Main(string[] args)
{
    const string urlSuffix = "://ws.cdyne.com/emailverify/Emailvernotestemail.asmx";
    string protocol = null;
    while(protocol == null)
    {
        Console.Write("Enter protocol (http, https): ");
        var line = Console.ReadLine();
        if (line != null) line = line.ToLower();
        if (line == "http" || line == "https")
            protocol = line.Trim();
    }
    var url = protocol + urlSuffix;
    Console.WriteLine("Using URL: " + url);
    Console.Out.Flush();

    var service = new EmailVerNoTestEmail(url);

    Console.WriteLine("Press any key to make the web service call...");
    Console.ReadKey(true);

    Console.WriteLine("Calling web service...");
    var resp = service.VerifyEmail("test@gmail.com", "test");
    Console.WriteLine("Response: " + resp);

    Console.WriteLine("Press any key to exit.");
    Console.ReadKey(true);
}

1 个答案:

答案 0 :(得分:-1)

除非系统受到压力,否则它自然会保持在某个内存级别。操作系统具有启发式功能,可以确定需要多少内存,并分配给高于所需内存的高点。为什么?分配和释放内存是昂贵的,如果程序可以在自己的沙箱中运行,那么为什么在系统没有压力的情况下减少它。

正如你所提到的,不是分配的内存量是一个问题,而是内存泄漏。我建议你运行perfmon并监控泄漏情况;阅读本MSDN CLR文章Investigating Memory Issues中要注意的事项。

编辑 :( 这是我之前提供的建议,但可能与主题重复有关/抱歉

要查看内存泄漏的迹象,可以激发perfmon并查看perfmon中的Private Bytes以查找这些迹象。请参阅Identify And Prevent Memory Leaks In Managed Code开始此过程。

要使用的另一个进程是在Windows任务管理器的“进程”选项卡上。 (查看+选择列,)检查句柄,GDI对象和用户对象。请注意程序的这些值。如果有手柄泄漏,如果你这样做,你会看到其中一个稳定地攀爬。在这些情况下,GDI很有可能。

通常,当OS运行应用程序时,它会尝试确定正在使用多少内存。它将为应用程序分配更多内存,以满足应用程序当前所需的内存。原因是,分配/解除分配内存是一个CPU密集型操作。为什么应用程序需要将应用程序所需的内容与驻留在内存池中进行并行,这将允许应用程序在不受操作系统干扰的情况下进行扩展和收缩。节省周期。

开发人员看到的内存水位高。如果系统没有受到压力,系统将不会回收任何内存并保持高水位线。在这个论坛中有许多帖子,用户说,处理完成,内存清理但操作系统仍然在内存点X显示我的应用程序,当它应该是内存点M(更低)。 Winform用户报告相同但如果最小化应用程序,突然报告的内存使用量下降到该M级别。这是通过设计完成的。最小化表明应用程序不需要内存,因为它不会与用户交互,操作系统将回收这一点。如果它不是一个winform并且操作系统没有压力,那么应用程序将保持在X的高水位。