性能调优

优化渲染和内存

Doconut 的资源概况主要受三件事支配:渲染 DPI、缓存内容和会话持续时间。本指南按影响顺序讲解各调节项。

分辨率 — 最大的杠杆

ImageResolution(25–300 DPI)决定渲染时间和图像大小。大多数格式默认 200 DPI;图像和 PSD 默认 100。

csharp
// 文档列表预览不需要打印质量
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { ImageResolution = 100 });

将 DPI 减半大约会使每页像素数降至四分之一——渲染更快,传输更小,缓存内存更少。对放大频繁的使用场景(CAD、工程图纸)保留 250–300 DPI。

对于嵌入大量图像的 PDF,PdfConfig 提供更细的调节:CompressImages + CompressQuality、ResizeImages + ResizeResolution,以及 CompressFast。对于普通图像,ImageConfig.MaxImagePixelSize(默认 3000 像素)限制输出大小。

页面缓存 — 内存 vs. 重新渲染

BaseConfig.CachePages(默认 true)在会话期间将每个渲染页面保存在内存中。这是交互式查看的合适默认设置——用户可以前后滚动。在以下情况下关闭它:

  • 文档体积庞大且仅查看一次,从头到尾,
  • 大量并发会话会导致缓存页面数量成倍增加,
  • 你更愿意为每次查看支付 CPU 而不是占用 RAM。
csharp
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { CachePages = false });

在客户端,ViewerConfig.CacheEnabled = true 在浏览器内存中预加载一个小的移动窗口,包含即将显示的页面图像。它是每次查看的预取缓存,而非持久的 localStorage。

会话 — 你看不见的内存

每个打开的会话都会保留已解析的文档模型以及(使用 CachePages)其渲染页面,直至滑动的 TimeOut(默认 60 分钟)自上一次请求起结束。以下两种做法可将其控制在合理范围:

  • 关闭已完成的内容。 viewer.CloseDocument(token) 可立即释放引擎,而不是等待空闲窗口结束。
  • 适当设置超时。 用户浏览两分钟的预览不需要一小时的会话:
csharp
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

请记住权衡:超时后小部件会显示 Document session not found. Please re-open document. ——请选择与实际阅读会话相匹配的超时时间。

特定格式开关

  • Excel:MemoryOptimizationPreference 默认开启,在渲染超大工作簿时可降低内存占用——保持开启,或在愿意以少量速度提升换取内存时将其设为 false;SheetNames / PrintArea 限制渲染仅针对重要内容。
  • 重定向模式有前置成本:DefaultRender = false 在打开时将整个文档转换为 PDF。它提供原生文本搜索,但在 500 页文档上,打开调用会承担此转换——不要盲目启用。
  • 在没有文档字体的服务器上运行 Word/PowerPoint:没有 Office 的 Windows Server 的字体远少于开发机器。缺失的字体会导致缓慢的回退探测和错误的度量;请安装这些字体,或将 FontFolders 指向包含它们的文件夹。

客户端策略

  • LargeDoc = true — 针对超大文档的懒加载策略;页面在用户接近时加载。
  • AutoLoad = false(默认)— 在实际调用 View(token) 之前不渲染。
  • ShowThumbs = false — 对单页或嵌入式预览跳过缩略图生成/请求。
  • 启用 FixedZoom 可避免自由缩放;当映射 C# ViewerConfig 时,为小屏幕调节 FixedZoomPercentMobile(C# 默认 75)。

启动一次,而非每次请求

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) 应放在 Application_Start 中,紧邻 DoconutHost.Initialize ——在每次请求中注册编码是浪费的工作;完全忘记它会导致旧版代码页文档失效。

启动后首次打开文档

Doconut 在应用程序首次打开文档时加载其文档引擎——在池启动后、每次回收后以及每个新应用程序域中。首次打开比后续打开更慢,而且实时防病毒会使其更慢:引擎从内存加载,Microsoft Defender 在加载时会扫描这些代码。文件夹排除无效,因为没有涉及文件。

在一台 4 核 Windows Server 2022 机器上测量,打开一个两页的 Word 文档:

首次文档其后每个文档
启用 Defender 实时保护约 70 秒0.3–7.5 秒,取决于格式
关闭 Defender 实时保护12–15 秒0.3–7.5 秒,取决于格式

一次性付出成本,先于用户:

  • 保持工作进程存活:将应用程序池的 启动模式 设置为 AlwaysRunning,并提升或禁用其 空闲超时,以免在安静的夜间卸载引擎。
  • 启动时预热:启用 IIS 应用程序初始化(站点上的 preloadEnabled="true"),并将其 initializationPage 指向打开小文档的页面。首位真实用户即可发现引擎已加载。
  • 为首次请求留出时间:负载均衡器的健康检查或具有短超时的上游代理可以放弃本可能成功的冷启动。

是否在服务器上更改防病毒设置取决于安全团队的决定;上述预热在不更改的情况下也能工作。

应用程序池

在单台服务器上,文档会话和缓存页面位于工作进程中。每次应用程序池回收——计划的回收、对 Web.config 的编辑,或池的 空闲超时(IIS 中默认 20 分钟)——都会清除它们,打开的查看器随后显示 Document session not found. Please re-open document.。

  • 将池的空闲超时和回收计划与用户实际阅读时长保持一致,或准备在回收后重新打开文档。
  • 将池以 64 位进程运行(关闭 启用 32 位应用程序)。大文档需要 32 位工作进程无法提供的地址空间。
  • Web 农场将会话保存在共享存储中,因此单个节点的回收不会导致会话丢失 — 参见 会话与安全。

调优清单

  1. 设置用户体验可接受的最低 ImageResolution。
  2. 在交互式查看时保持 CachePages 开启;在一次性或高并发场景下关闭。
  3. 显式关闭会话;在使用突发的情况下缩短 TimeOut。
  4. 在客户端对大文档使用 LargeDoc + 默认 AutoLoad = false。
  5. 仅在需要带文本的 PDF 投影时使用 DefaultRender = false。

此页面对您有帮助吗?