Office 加载项的资源限制和性能优化
质量加载项必须在 CPU 核心使用率、内存使用率、可靠性以及 Outlook 加载项的正则表达式评估响应时间方面,在特定的要求内执行。 这些限制有助于确保用户性能和缓解拒绝服务攻击。 请务必使用一系列可能的数据在目标 Office 应用程序上测试 Office 加载项,并针对以下运行时使用限制来衡量其性能。
加载项的资源使用限制
以下运行时资源限制适用于在 Windows 和 Mac 上的 Office 客户端中运行的所有加载项,但不适用于移动应用或浏览器中。
CPU 核心使用率 - 默认情况下,单个 CPU 核心使用率阈值为 90%,在 5 秒间隔内观察到 3 次。
如果 Office 客户端检测到加载项的 CPU 核心使用率高于阈值,则会显示一条消息,询问用户是否要继续运行加载项。 如果用户选择继续,Office 客户端在该编辑会话期间不会再次询问用户。 Office 客户端检查 CPU 核心使用率的默认间隔为每 5 秒一次。 如果用户运行 CPU 密集型加载项,管理员可以使用 AlertInterval 注册表项提高阈值,以减少此警告消息的显示。
内存使用 - 默认内存使用阈值,根据设备的可用物理内存动态确定。
默认情况下,当 Office 客户端检测到设备上的物理内存使用率超过可用内存的 80%时,客户端将开始监视加载项的内存使用情况。 此操作在内容和任务窗格加载项的文档级别和 Outlook 外接程序的邮箱级别完成。如果文档或邮箱级别的一组加载项的物理内存使用率超过 50%,则默认间隔为 5 秒,客户端会警告用户。 此内存使用率限制使用物理内存而非虚拟内存来确保具有有限 RAM 的设备(如平板电脑)保持良好性能。 管理员可以使用 MemoryAlertThreshold Windows 注册表项作为全局设置,以显式限制替代此动态设置。 他们还可以使用 AlertInterval 键调整警报间隔。
故障容错 - 在文档会话期间,默认限制为 4 个崩溃。
管理员可以通过使用 RestartManagerRetryLimit 注册表项来调整故障阈值。
应用程序阻止 - 长时间无响应阈值 5 秒。
这会影响加载项和 Office 应用程序的用户体验。 发生这种情况时,Office 应用程序会自动重启文档或邮箱的所有活动加载项 ((如果适用) ),并警告用户哪个加载项无响应。 当加载项在执行长时间运行的任务时不定期产生处理,则它们会达到此阈值。 本文后面列出了一些有助于确保加载项不会阻止 Office 应用程序的技术。 管理员无法替换此阈值。
任务窗格和内容外接程序
如果任何内容或任务窗格加载项超出上述 CPU 核心或内存使用率阈值,或崩溃的容错限制,则相应的 Office 应用程序向用户显示警告。 此时,用户可以执行下列操作之一:
- 重新启动外接程序。
- 取消有关超出该阈值的后续警报。 理想情况下,用户应从文档中删除加载项。 继续使用加载项将面临进一步的性能和稳定性问题的风险。
Outlook 外接程序
如果任何 Outlook 加载项超过上述 CPU 核心或内存使用量阈值或崩溃的容错限制,则外接程序将变得不可用。 Exchange 管理员中心显示加载项的状态。
注意
尽管只有 Windows 上的 Outlook (经典) 和 Mac 上的 Outlook 监视资源使用情况,但如果其中任一客户端使 Outlook 加载项不可用,该外接程序在Outlook 网页版、移动设备和新的 Outlook on Windows 中也变得不可用。
除了 CPU 核心、内存和可靠性规则外,Outlook 加载项还应遵守以下激活规则。
正则表达式响应时间 - Outlook 计算 Outlook 外接程序清单中的所有正则表达式的默认阈值为 1,000 毫秒。 超过该阈值会导致 Outlook 稍后重新尝试计算。
管理员可以通过在 Windows 注册表中使用组策略或特定于应用程序的设置来调整此默认阈值 1,000 毫秒。
正则表达式重新计算 - Outlook 重新计算清单中所有正则表达式的默认限制为 3 次。 如果评估未能在限制的时间内评估 3 次,Outlook 会使加载项不可用。
管理员可以调整此次数以重试评估,方法是在 Windows 注册表中使用 OutlookActivationManagerRetryLimit 键的组策略或特定于应用程序的设置。
Excel 加载项
与工作簿交互时,Excel 加载项具有重要的数据传输限制。
- Excel 网页版将请求和响应的有效负载大小限制为 5MB。 如果超过该限制,将引发
RichAPI.Error
。 - 读取操作的范围限制为 5,000,000 个单元格。
如果预期用户输入将超过这些限制,请在调用 context.sync()
之前检查数据。 根据需要将操作拆分为较小的部分。 调用 context.sync()
每个子操作,以避免这些操作再次批处理在一起。
大范围通常超过这些限制。 加载项可能能够使用 RangeAreas 在较大范围内战略性地更新单元格。 有关使用 RangeAreas
的详细信息,请参阅 在 Excel 外接程序中同时处理多个区域。有关在 Excel 中优化有效负载大小的其他信息,请参阅 有效负载大小限制最佳做法。
验证遥测日志中的资源使用情况问题
Office 提供遥测日志,用于维护本地计算机上运行的 Office 解决方案 (加载、打开、关闭和错误) 某些事件的记录。 这包括 Office 外接程序中的资源使用问题。 如果已设置遥测日志,则可以使用 Excel 在本地驱动器上的以下默认位置打开遥测日志。
%Users%\<Current user>\AppData\Local\Microsoft\Office\16.0\Telemetry
对于遥测日志跟踪的外接程序的每个事件,都有事件的发生日期/时间、事件 ID、严重性、事件的简短描述性标题、外接程序的友好名称和唯一 ID,以及记录事件的应用程序。 刷新遥测日志以查看当前跟踪的事件。 下表显示了之前在遥测日志中跟踪的 Outlook 外接程序的示例。
日期/时间 | 事件 ID | Severity | 标题 | 文件 | ID | 应用程序 |
---|---|---|---|---|---|---|
2022/10/8 下午 5:57:10 | 7 | 不适用 | 外接程序清单已成功下载 | Who's Who | 69cc567c-6737-4c49-88dd-123334943a22 | Outlook |
2022/10/8 下午 5:57:01 | 7 | 不适用 | 外接程序清单已成功下载 | 333bf46d-7dad-4f2b-8cf4-c19ddc78b723 | Outlook |
下表列出了遥测日志针对 Office 加载项跟踪的事件。
事件 ID | 标题 | Severity | 说明 |
---|---|---|---|
7 | 外接程序清单已成功下载 | 不适用 | Office 应用程序已成功加载和读取 Office 加载项清单。 |
8 | 外接程序清单未下载 | 关键 | Office 应用程序无法从 SharePoint 目录、公司目录或 AppSource 加载 Office 外接程序的清单文件。 |
9 | 无法分析外接程序标记 | 关键 | Office 应用程序加载了 Office 外接程序清单,但无法读取应用的 HTML 标记。 |
10 | 外接程序占用了太多 CPU | 关键 | 在有限的时间内,Office 外接程序使用了超过 90% 的 CPU 资源。 |
15 | 由于字符串搜索超时,外接程序已被禁用 | 不适用 | Outlook 外接程序搜索电子邮件的主题行和消息,以确定是否应使用正则表达式来显示它们。 “文件”列中列出的 Outlook 外接程序已被 Outlook 禁用,因为它在尝试匹配正则表达式时超时多次。 |
18 | 外接程序已成功关闭 | 不适用 | Office 应用程序能够成功关闭 Office 加载项。 |
19 | 外接程序遇到运行时错误 | 严重 | Office 外接程序遇到一个导致它失败的问题。 有关详细信息,请使用遇到错误的计算机上的 Windows 事件查看器查看“Microsoft Office 通知”日志。 |
20 | 外接程序未能验证许可 | 严重 | 无法验证 Office 外接程序的许可信息,且其可能已过期。 有关详细信息,请使用遇到错误的计算机上的 Windows 事件查看器查看“Microsoft Office 通知”日志。 |
有关详细信息,请参阅部署遥测仪表板和使用遥测日志排查 Office 文件和自定义解决方案。
设计和实现技术
虽然 CPU 和内存使用率、崩溃容忍度和 UI 响应能力的资源限制适用于仅在 Office 桌面客户端中运行的 Office 外接程序,但如果您希望外接程序在所有支持客户端和设备上都能令人满意地执行,则优化应是一个优先事项。 如果您的外接程序要执行长时间运行的操作或处理大型数据集,则优化尤为重要。 以下列表建议了一些技术,可将 CPU 密集型或数据密集型操作分解为较小的区块,以便外接程序避免过度消耗资源并使 Office 应用程序保持响应。
如果外接程序需要从无限数据集读取大量数据,则可以在从表中读取数据时应用分页,或者在每个较短的读取操作中减小数据大小,而不是尝试在单个操作中完成读取。 可以通过全局对象的 setTimeout 方法执行此操作,以限制输入和输出的持续时间。 它还会处理定义区块中的数据,来代替随机无限数据。 另一个选项是使用 异步 来处理 Promises。
如果外接程序使用 CPU 密集型算法来处理大量数据,则可以使用 Web 辅助角色 在后台执行长时间运行的任务,同时在前台运行单独的脚本,例如在用户界面中显示进度。 Web Worker 不会阻止用户活动并允许 HTML 页面保持响应能力。 有关 Web Worker 的示例,请参阅 Web Worker 的基本信息。
如果外接程序使用 CPU 密集型算法,但可以将数据输入或输出划分为较小的集,请考虑创建一个 Web 服务,将数据传递到 Web 服务以卸载 CPU,并等待异步回调。
针对预期的最大数据量测试加载项,并限制加载项处理的数据量不得超过此限制。
使用特定于应用程序的 API 改进性能
使用应用程序特定的 API 模型中的性能提示提供了使用适用于 Excel、OneNote、Visio 和 Word 的应用程序特定 API 时的指南。 总之,你应该:
- 仅加载必要的属性。
-
尽量减少同步 () 调用数。 有关如何在代码中管理
sync
调用的详细信息,请阅读避免在循环中使用 context.sync 方法。 - 尽量减少创建的代理对象数。 还可以取消跟踪代理对象,如下一部分所述。
未跟踪不需要的代理对象
在调用 之前,代理对象一直RequestContext.sync()
保留在内存中。 大型批处理操作可能会生成许多代理对象,加载项只需用到这些对象一次,并且可以在批处理执行之前从内存中释放。
方法 untrack()
从内存中释放 对象。 此方法在许多特定于应用程序的 API 代理对象上实现。 使用大量代理对象时,在加载项完成调用 untrack()
后,应会获得明显的性能优势。
注意
Range.untrack()
是 ClientRequestContext.trackedObjects.remove(thisRange) 的快捷方式。 任何代理对象都可以通过从上下文中的跟踪对象列表中删除它来取消跟踪。
以下 Excel 代码示例使用数据填充所选区域,一次一个单元格。 将值添加到单元格后,表示该单元格的区域将被取消跟踪。 在选定的 10,000 到 20,000 个单元格区域运行此代码,首先使用 cell.untrack()
行,然后取消使用。 应会注意到,使用 cell.untrack()
行的代码比不使用的代码运行速度要快。 此外,可能还会注意到之后的响应时间更快,因为清理步骤花费的时间更少。
Excel.run(async (context) => {
const largeRange = context.workbook.getSelectedRange();
largeRange.load(["rowCount", "columnCount"]);
await context.sync();
for (let i = 0; i < largeRange.rowCount; i++) {
for (let j = 0; j < largeRange.columnCount; j++) {
let cell = largeRange.getCell(i, j);
cell.values = [[i *j]];
// Call untrack() to release the range from memory.
cell.untrack();
}
}
await context.sync();
});
请注意,只有在处理数千个对象时,需要取消跟踪对象才变得重要。 大多数加载项不需要管理代理对象跟踪。