对web服务或web请求使用HTTPS时,内存使用问题

本文关键字:web 内存 问题 HTTPS 请求 服务 | 更新日期: 2023-09-27 18:19:55

EDIT:经过评论中的长时间讨论,我最初的问题似乎并没有真正反映出发生了什么

  • 当使用HTTPS时,当发出第一个HTTPS请求(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用于web服务的成本。

我知道会有一些来自"如果更高的内存使用率没有引起问题,为什么要担心?"阵营的回应。总的来说,我同意这一点——任务管理器中的内存使用率数字通常不能表明应用程序是否按预期工作。如果该应用程序严格在内部使用,只要它不是其他问题的症状,我就可以接受。但我们的应用程序是与消费者机器一起部署的,所以我们必须像担心实际问题一样担心对问题的感知。因此,如果有任何方法可以解决这个问题,我将不胜感激!

最后,我在下面的测试代码中使用的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);
}

对web服务或web请求使用HTTPS时,内存使用问题

除非系统受到压力,否则它自然会保持在某个内存级别。操作系统具有试探法,可以确定需要多少内存,并将其分配给高于所需内存的高点。为什么?内存的分配和释放是昂贵的,如果一个程序可以在自己的沙盒中运行,如果系统没有压力,为什么要减少它呢。

正如您所提到的,关注的不是分配的内存量,而是内存的泄漏。我建议您运行perfmon并监视泄漏;请阅读MSDN CLR文章《调查内存问题》中的注意事项。

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

要查看内存泄漏的迹象,可以启动perfmon并查看perfmon中的Private Bytes以查找这些迹象。请参阅识别和防止托管代码中的内存泄漏以开始该过程

另一个要使用的进程位于Windows任务管理器的"进程"选项卡上。(查看+选择列,)选中句柄、GDI对象和USER对象。请为您的程序遵守这些值。如果没有句柄泄漏,那么在这些场景下,你会看到其中一个正在稳步攀升。GDI很可能会出现这种情况

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

开发人员看到的是内存的高水位线。如果系统没有受到压力,系统将不会回收任何内存并保持高水位标记。这个论坛上有很多帖子,用户说,处理完成,内存清理完毕,但操作系统仍然显示我的应用程序在内存点X,而它应该是内存点M(更低)。Winform用户报告的情况相同,但如果将应用程序最小化,则会突然报告内存使用情况;下降到M电平。这是经过设计的。最小化意味着应用程序不需要内存,因为它不会与用户交互,操作系统会收回这一点。如果它不是winform,并且操作系统没有受到压力,则应用程序将保持;在X的高水位标记处。