伟大的Skype for Business记忆之谜

本文由 Kenn Guilstorf 撰写,Skype for Business升级工程师。

作为一名升级工程师,我帮助客户解决一些更“好”的Skype for Business问题。 最近,我收到了相当多的“基于性能”的案例- 基本上,抱怨Skype for Business速度缓慢或迟缓,不允许应用程序共享,或者只是使用过多内存。 很多时候,对这些情况的调查表明,用户让Skype for Business运行了数周;并且,随着时间的推移,内存会逐渐增加,直到它影响性能。 当我让 Skype 运行很长时间时,我甚至自己也注意到了它。 那么,Skype 在做什么,为什么它持有这么多内存? (这里有一点提示:这是正常且经过设计。没有任何错误 - 任何和每个本机程序都运行到此中。)

它可以咀嚼多少内存?

修复任何问题的第一步是了解问题,了解任何问题的第一步是定义问题。 这并不像听起来那么容易。

首次启动 Skype for Business (SfB) 时,如果可以将 100 MB 计算为较小的) ,内存使用量将相对较少 (。 我们可以看到,在任意数量的工具(如 任务管理器)中都会出现这种情况:

屏幕截图显示任务管理器窗口中的 Lync 应用详细信息,内存值为 83,428K。

图 1:不要被愚弄:Lync.exe 是 SfB (32 位版本)

随着时间的推移,进程使用的内存量将会增加。 它增长的大小取决于 Skype 的使用量、用途等。 例如,大约 24 小时后,同一客户端如下:

显示任务管理器窗口中 Lync 应用详细信息的屏幕截图,其中内存增长到 115,196K。

图 2:24 小时后相同的 SfB

因此,Skype 在 24 小时内消耗了大约 32 MB。 这不多,对吗? 这真的不是 - 直到我解释 Skype 只是闲置了所有 24 小时。 基本上,我在计算机上开始Skype for Business,将其锁定,然后等待大约 24 小时才解锁它。 使用时,收费要高得多,尤其是在我加入会议、在这些会议中使用了应用共享或桌面共享、使用了 IM 等。 我见过Skype for Business内存使用量在一天内增加到 300-500 MB 的情况。 使用一周或多周后,内容可能会变小,尤其是在内存受限得多的 32 位客户端上。

显示内存

有许多工具可以分析内存。 最受欢迎的一种(至少在 Microsoft)是 VMMap v3.26 中提供的 SysInternals 工具 VMMap。 可以使用它来查看进程内存,并查看是否可以分析Skype for Business内存。

下载 VMMap 后,请运行它。 启动时,它将打开一个进程列表,以便你可以选择要检查的进程。 我将选择 lync.exe 并单击“ 确定”。

显示“开头的 V m 映射”的屏幕截图,其中选择了 Lync。

图 3:开始时的 VMMap

接下来,你将看到一个图形,该图形是所选可执行文件的当前内存配置文件的多色表示形式( 在本例中为 Lync.exe)。

显示内存配置文件的多色表示形式的屏幕截图。

图 4:最近启动的开始 VMMap Lync.exe

这里有很多信息,描述这一切将填满一个或多个自己的博客文章。 如果你感兴趣,有几本伟大的书籍和在线文章可以帮助解释它。 (个人,我推荐杰弗里·里希特的“高级 Windows”-目前已绝版,但仍在解释内存工作原理方面非常出色。可以在你最喜欢的书店找到它的已用副本。)

可以看到, 任务管理器 中显示的内存与 VMMap 中的任何类别都不一致。 任务管理器 是一种更通用的表示形式;这是准确的,它只是不计算所有内容。 VMMap 要全面得多。

下面是 24 小时等待期后的 Skype 实例:

显示 24 小时后 Skype 的 V m 映射的屏幕截图。

图 5:24 小时后用于 Skype 的 VMMap

内存在哪里?

如果比较每个单独的类别,则不会真正排队。 实际上很难找到占用内存的内容,因为随着对象和内存请求的发出和释放,内存的类别会波动,并且内存将保留并提交用于存储各种对象。 出于此博客的目的,“知识内核” (,无论如何,) 是“免费”类别。 在我们的示例中,“可用”内存是 Lync 可执行文件“保留”的所有可用空间。 但 任务管理器中只显示特定类型的“已提交”内存。 保留内存不计入,因为它未使用。

那么,内存在哪里? 这变得很难确定,因为内存不会丢失。 与人们普遍的看法相反,Skype 团队没有得到桌面内存制造商的补贴。 没有恶意的阴谋让客户升级任何系统或内存。 这甚至不是计划过时的情况。 真相有点难以解释。

让我们回溯一下,使事情更清晰。 首次启动 Skype for Business 客户端时,它的内存占用相对较小(通常为 100 MB 左右),具体取决于它为你跟踪的联系人数和其他开销 (可以在) 上面的数据中清楚地看到这一点。 几天后,你会注意到,此占用空间会增加到几十万字节到几兆字节。 在某些情况下,这可能是一个问题,但并不一定是Skype for Business本身的问题。 相反,它是 Windows 编程范例及其本机处理内存方式的一种影响。

Windows 编程是什么?

我只想在此处提供 Windows 内存的简单视图。 Windows 内存通过昂贵的 (来处理计算机周期和资源) 称为分配和取消分配的过程。 当程序需要内存时,它会要求 Windows 分配内存。 当内存通过时,程序会要求 Windows 取消分配它。 在内部,Windows 会经历多个进程来管理内存请求。

发出请求时,Windows 会检查它是否已提交到进程的内存,但进程是否未使用。 Windows 希望查看是否有足够大的内存块可以使用。 如果有,系统使用它,并继续其快乐的方式。 如果没有,则检查预留内存。 如果有足够大的保留内存块,它将 (在操作系统定义的区块(称为“pages”) )中提交,并将变量存储在其中。 现在已提交内存,我们刚刚增加了可执行文件的内存占用量。

如果没有足够的保留内存来处理请求,会发生什么情况? 操作系统尝试保留更多内存(如果可以)。 下面是 32 位体系结构和 64 位体系结构之间的差异的发生地。 32 位进程最多只能使用 4 GB 内存。 这是因为 4 GB 是 32 位寄存器可以寻址的最大量。 (A 位只能包含 1 或 0 – 二进制。因此,32 位表示 232 是允许) 的最高地址。 由于采用 32 位体系结构,该内存中只有大约 2 GB 分配给进程本身,其余内存由操作系统用于映射公共 DLL、处理常见的内核模式对象,等等。 在 64 位系统中,64 位长寄存器可以处理 264,这大约为 18 EB。 但是,Windows 人为地将可用于保留的内存量限制在 2 TB 到 4 TB 之间, (TB) ,具体取决于 Windows 版本。

保留内存后,它将提交,然后像以前一样使用。 取消分配过程在很大程度上是相反的 - 除了一两个小但重要的细节。

首先,除非请求,否则 Windows 永远不会“清除”内存。 取消分配内存时,它将在 Windows 内存映射中标记为 可用 。 它持有的任何内容仍然存在,并且将保留在那里,直到它被另一个分配覆盖。 接下来,除非请求取消提交内存,否则 Windows 很少会取消提交内存。 正如我之前所说,内存操作的资源开销相当高。 因此,如果某个程序需要以前分配的内存,则 Windows 假定它可能再次需要该内存,并会推迟取消提交内存,直到它必须这样做。 最后,Windows 永远不会“合并”内存。 这意味着,Windows 释放的内存永远不会“聚合”,并且可用内存块永远不会“一起移动”,以生成更大的可用内存块。 (所有这些函数都合并到称为“垃圾回收”的类别中。.NET Framework有一些垃圾回收功能。但是,Skype for Business是“本机”或 non-.NET application.)

Skype for Business每秒处理许多大小可变的对象。 它必须这样做,才能成为我们希望它的惊人工具。 我们要求它管理联系人、管理日历 (会议) 、与我们的朋友、亲戚和同事进行即时消息,甚至使用语音和视频与他们交谈、共享桌面或窗口等。 嗯,引用已故的,伟大的罗伯特海因莱恩,等等:“没有免费的午餐。

管理如此多且大小不同的对象通常会创建大小可变的内存区块的分配和取消分配。 随着时间的推移,这会导致内存碎片(有时严重)增加Skype for Business的内存占用量。

示例可能更能说明这一点。 假设 Skype (或任何本机程序实际上) 分配 64 个对象,编号为 1-64,每个对象的大小为 4 K 字节:

显示 Skype 64 对象的屏幕截图。

图 6:64 个对象,每个对象使用 4 KB 内存

这会导致 256 KB 内存分配和承诺。 现在,假设程序不需要偶数对象,因此会释放它们:

显示释放的所有偶数对象的屏幕截图。

图 7:释放所有偶数对象可释放 128 KB 内存!

如果使用 VMMap 或类似工具) 查看总体内存 (的较大图景,你将看到“ ”部分中可能 (提交的列之一,但这完全取决于程序请求内存的方式,) 内存减少了 128 KB,而 “免费 ”部分增加了 128 KB。 在任务管理器中,程序现在仅拥有 128 KB 字节的内存。

接下来,假设程序有一个必须存储的 8 KB 对象。 这应该很简单。 毕竟,它具有 128 KB 的可用空间。 但是,尝试存储该 8 KB 对象将创建新的内存预留,而不是将内存存储在 128 KB 可用空间中。 这是因为,如果你查看内存,你可以看到它仍然被分割成 4 KB 的区块! Windows 没有足够大的内存块来容纳 8 KB 对象,因此它必须保留更多内存并将其提交到程序。

这是一个相当阴谋的示例,但它说明了 Skype 内存管理的难度。 Skype 管理大量对象,这些对象没有易于定义的大小。 这些对象都是可变长度的。 这意味着,当对象被存储和释放时(尤其是在很长一段时间内,例如几天或几周),内存碎片可能会变得严重,并且由于 Windows 必须分配更多内存来存储新对象,内存占用量会过度增长。

当这导致 32 位客户端出现问题时,我们经常建议迁移到 64 位客户端,因为由于 64 位与 32 位体系结构的内存限制要小得多。 但是,过多的内存增长以及其他注意事项,甚至可能导致 64 位客户端出现迟缓。 这些其他注意事项包括整体系统内存、磁盘速度 (,因为程序内存通常由 Windows 分页文件中 的虚拟内存) 、打开的其他应用程序数量等。 在这两种情况下,随着Skype for Business内存占用量随着时间的推移而增长,其性能就越差。 在 32 位客户端案例中,这可能会导致 Skype 所需的较大对象(例如用于应用程序共享的内部缓冲区)耗尽空间并导致故障。

平心而论,内存只是随时间推移消耗的一种资源,但它 是最 明显的。 句柄使用量可能会增加,线程将随着时间的推移而增加,分页池内存将增加,等等。 这些增加中的每一个都会对过程产生影响,在某些情况下,也会对整个操作系统产生影响。 这是我们建议用户退出并重启 Skype 每日 (或至少每周) 作为最佳做法的众多原因之一,即使对于 64 位客户端也是如此。

对此,我该怎么做,是否可以强制 Skype 重启?

有几种方法可以强制重启 Skype,但没有一种最佳方法。 当然,其中一种方法是用户教育。 在大多数情况下,用户是桌面使用情况的仲裁者,因此,教他们在离开一天时注销并关闭 Skype 是务实的。 也可以通过编写自定义脚本或可执行文件,然后将任一脚本或可执行文件作为任务计划程序任务运行,以强制步骤完成此操作。 这种方法有点麻烦,即使 Skype 处于“使用中” (也可能导致 Skype 循环,尽管这可以通过任务计划程序条件) 有所缓解。 还有用于桌面和计算机管理、潜在 BIOS 选项等的第三方机会。

底线是,最好是Skype for Business每天或至少每周循环一次。 如果你可以定期培训用户回收Skype for Business,或者至少在事情变得奇怪时,你的支持人员呼叫可能会少得多,用户会更满意。