内容推荐服务提供商 Taboola 如何利用 LoAF 将其发布商合作伙伴网站的 INP 提升高达 36%。

Taboola 如何利用 Long Animation Frames API (LoAF) 并采用智能让渡策略,在不影响广告效果的前提下提高发布商网站的响应速度。

David Belford
David Belford

Interaction to Next Paint (INP) 是一项用于评估网站对用户输入的响应情况的指标。INP 衡量的是从用户开始互动(例如点击、点按或输入)到产生视觉反馈所用的时间。INP 将于 2024 年 3 月取代 First Input Delay (FID) 成为一项 Core Web Vitals 指标

Taboola 是全球领先的内容发现平台,每秒在开放网络上提供 50 万条推荐内容。这些建议可帮助 Taboola 的 9,000 家独家发布商合作伙伴创收并吸引受众群体。发布商使用 JavaScript 在其网页上呈现推荐内容。

由于第三方 JavaScript 会影响网页快速响应用户输入的能力,因此 Taboola 一直在努力减小其 JavaScript 文件的大小和执行时间。Taboola 一直在重新设计其整个渲染引擎,并直接使用浏览器 API(不使用抽象层)来尽可能减少对 INP 的影响。

本使用情形分析介绍了 Taboola 如何使用新的 Long Animation Frames (LoAF) API 来衡量其对实际网页响应速度的影响,从而改进 INP,以及后续如何通过应用特定优化措施来改善用户体验。

TBT 作为 INP 的代理

总阻塞时间 (TBT) 是一项基于实验室的指标,用于识别主线程被阻塞的时间是否过长,以至于可能会影响网页响应速度。衡量响应能力的现场指标(例如 INP)可能会受到高 TBT 的影响。Annie Sullivan移动设备上 TBT 与 INP 之间的相关性进行的一项调查表明,当主线程阻塞时间尽可能缩短时,网站更有可能获得良好的 INP 分数。

这种相关性,再加上 Taboola 的发布商对高 TBT 的担忧,促使 Taboola 专注于尽可能减少其对该指标的影响。

有关主线程阻塞时间的 Lighthouse 审核的屏幕截图。多个脚本总共将主线程阻塞了 2,630 毫秒,其中第三方 JavaScript 贡献了 712 毫秒。Taboola 的 RELEASE.js 脚本占用了大部分第三方阻塞时间,为 691 毫秒。
使用 Taboola 的旧版引擎时,RELEASE.js 等脚本会阻塞主线程 691 毫秒。

Taboola 将 TBT 用作 INP 的代理指标,开始监控和优化 JavaScript 执行时间,以限制其对核心网页指标的潜在影响。他们首先执行了以下操作:

不过,Taboola 发现使用这些工具分析 TBT 存在一些限制:

  • Long Tasks API 无法将任务归因于来源网域或特定脚本,因此更难识别长时间运行的任务的来源。
  • Long Tasks API 仅识别长时间运行的任务,而不是可能导致渲染延迟的任务和布局更改的组合。

为了应对这些挑战,Taboola 加入了 Long Animation Frames (LoAF) API 初始版本试用计划,以便更好地了解该 API 对用户输入响应速度的实际影响。源试用可让开发者使用新功能或实验性功能,以便测试用户可在有限时间内试用的新兴功能。

需要重点强调的是,此挑战中最困难的方面在于,如何在成功改进 INP 的同时,不影响任何广告 KPI(关键绩效指标),也不会导致发布商的资源延迟。

使用 LoAF 评估 INP 影响

当渲染更新延迟超过 50 毫秒时,就会出现长动画帧。通过找出导致界面更新缓慢的原因(而不仅仅是长时间运行的任务),Taboola 能够分析其对实际应用中网页响应速度的影响。通过观察 LoAF,Taboola 能够:

  1. 将条目归因于特定的 Taboola 任务。
  2. 在将特定功能部署到生产环境之前,观察其中的性能问题。
  3. 收集汇总数据,以便在 A/B 测试中比较不同的代码版本,并报告关键的成功指标。

以下 JavaScript 是生产环境中使用的简化版本,用于收集 LoAF 以隔离 Taboola 的影响。

function loafEntryAnalysis (entry) {
  if (entry.blockingDuration === 0) {
    return;
  }

  let taboolaIsMajor = false;
  const hasInteraction = entry.firstUIEventTimestamp > 0;
  let taboolaDuration = 0;
  const nonTaboolaLoafReport = {};
  const taboolaLoafReport = {};

  entry.scripts.forEach((script) => {
    const taboolaScriptBlockingDuration = handleLongAnimationFrameScript(script, taboolaLoafReport, nonTaboolaLoafReport);
    taboolaDuration += taboolaScriptBlockingDuration;

    if (taboolaScriptBlockingDuration > 0 || taboolaDuration > entry.duration / 2) {
      taboolaIsMajor = true;
    }
  });

  generateToboolaLoafReport(taboolaLoafReport, nonTaboolaLoafReport, hasInteraction, taboolaIsMajor);

  if (hasInteraction) {
    const global = _longAnimationFramesReport.global;
    global.inpBlockingDuration = Math.max(global.inpBlockingDuration, entry.blockingDuration);

    if (taboolaIsMajor) {
      global.taboolaInpBlockingDuration = Math.max(global.taboolaInpBlockingDuration, entry.blockingDuration);
    }
  }
}

const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    loafEntryAnalysis(entry);
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });
  • 借助 loafEntryAnalysis 函数,Taboola 能够识别出它是主要贡献者的条目。
  • 如果 Taboola 导致的总脚本时长超过一半,或者 Taboola 脚本的运行时间超过 50 毫秒,则 Taboola 被视为主要贡献者。
  • 如果用户互动因动画帧过长而延迟,系统会生成 firstUIEventTimeStamp。最长的阻塞时长被视为总体 INP 得分。我们还可以确定 Taboola 何时触发 firstUIEventTimeStamp 来计算 Taboola INP 分数。

通过 LoAF 收集的数据帮助 Taboola 创建了以下归因表,该表可确定可应用收益优化机会的领域。

脚本 时长(毫秒)
vpaid/units/33_6_8/infra/cmTagINLINE_INSTREAM.js:106517 997
vpaid/units/33_6_8/infra/cmTagFEED_MANAGER.js:496662 561
vpaid/vPlayer/player/v15.8.6/OvaMediaPlayer.js:44631 336
libtrc/impl.20231212-23-RELEASE.js:821090 857
publisher_name/pmk-20220605.5.js:7728 336
libtrc/card-interference-detector.20231219-7-RELEASE.es6.js:183 239
由 Taboola RUM 捕获的 LoAF 脚本条目

TRECS 引擎:新的创收策略

除了使用 LoAF 更好地了解脚本优化机会之外,Taboola 还重新设计了整个渲染引擎,以显著缩短 JavaScript 执行时间和阻塞时间。

TRECS(Taboola Recommendations Extensible Client Service,Taboola 推荐可扩展客户端服务)可维护客户端渲染和发布商当前的 JS 代码,同时减少加载 Taboola 推荐所需的强制性文件数量和大小。

使用 LoAF 识别出渲染阻塞任务后,“性能衰减器”可以在使用 scheduler.postTask() 让步于主线程之前分解这些任务。此设计可确保尽快执行面向用户的重要工作(例如渲染更新),而无需考虑可能占用主线程的任何现有任务。

以下是“Performance Fader”任务运行程序的 JS 代码段:

/**
* Send a task to run using the Fader. The task will run using the browser Scheduler, by the configuration settings, or immediately.
* @param task
* @param isBlocker
*/
function sendTaskToFader (task, isBlocker = true) {
  const publisherFaderChoice = fillOptimizationGlobals(); // Loading publisher choice
  const applyYielding = publisherFaderChoice === OptimizationFaderType.Responsiveness;

  if (applyYielding) {
    return runAsPostTask(task, isBlocker);
  }

  return runImmediately(task);
}

/**
* Yielding method using scheduler.postTask and falling back to setTimeout when it's not availabe based on the publisher choice
*/
function runAsPostTask (task, isBlocker = true) {
  if ('scheduler' in window && 'postTask' in scheduler) {
    const priority = isBlocker ? 'user-blocking': 'background';

    return window?.scheduler?.postTask(task, { priority });
  }

  const publisherChoiceEnableFallback = fillPublisherChoices();

  if (publisherChoiceEnableFallback) {
    return new Promise(resolve => {
      window.setTimeout(() => {
        resolve(task());
      }, 0);
    });
  }

  return runImmediately(task);
}

sendTaskToFader 函数

  • 使用 runAsPostTask,该 API 在后台使用 scheduler.postTask()(如果该 API 可用),否则会回退到 setTimeout
  • 此函数将函数调用封装在会导致动画帧过长和 INP 的代码部分中。它将这些代码部分拆分为更短的任务,从而减少 INP。

业务指标

借助 LoAF,Taboola 能够更好地了解其对 INP 的影响。该工具还突出显示了可作为新 TRECS 引擎一部分的脚本优化机会。

为了确定 TRECS 和 Performance Fader 的影响,Taboola 开展了一项 A/B 测试,在出版商合作伙伴小组中,将 INP 与不使用脚本的现有引擎进行了比较。

下表显示了 Taboola 广告资源网中 4 个匿名发布商的 INP 结果(以毫秒为单位,位于第 75 百分位)。

发布方 采用 TRECS + Performance Fader 的 INP 使用现有引擎的 INP INP 降幅 (%)
发布商 A 48 75 36%
发布商 B 153 163 6%
发布商 C 92 135 33%
发布商 D 37 52 29%

幸运的是,在测试面板上启用 TRECS 和 Performance Fader 后,广告点击率和每千次展示收入 (RPM) 等业务指标并未受到负面影响。随着 INP 的这一积极改进,广告 KPI 方面也没有出现任何负面结果(正如预期的那样),Taboola 将逐步改善其发布商对其产品的看法。

之前突出显示的同一客户的另一次 Lighthouse 运行表明,在使用新引擎时,Taboola 的主线程阻塞时间显著缩短。

一张屏幕截图,显示了应用新的 TRECS 和 Performance Fader 引擎来缩短主线程阻塞时间后,Lighthouse 审核得出的主线程阻塞时间。审核时间缩短至仅 206 毫秒,而优化前为 712 毫秒。
Taboola 的新引擎帮助 RELEASE.js 等脚本将 TBT 减少了 485 毫秒(-70%)

这表明,使用 LoAF 识别 INP 的原因并部署后续的让步技术(通过 Performance Fader)可让 Taboola 的合作伙伴在广告和网页效果方面取得最大成功。

总结

优化 INP 是一项复杂的过程,尤其是在合作伙伴网站上使用第三方脚本时。在开始优化之前,将 INP 归因于特定脚本可消除任何猜测,并避免对其他网站性能指标造成潜在损害。事实证明,LoAF API 是一种非常有价值的工具,可用于识别和解决 INP 问题,尤其是对于嵌入的第三方,它可帮助他们找出特定的 SDK 改进机会,同时消除页面上其他技术的干扰。

如果与良好的让步策略(例如使用 scheduler.postTask())结合使用,LoAF 可以帮助您观察和了解网页响应缓慢的原因,从而为您提供改进网站 INP 所需的信息。

特别感谢 Google 的 Gilberto Cocchi、Noam Rosenthal 和 Rick Viscomi,以及 Taboola 工程和产品团队的 Dedi Hakak、Anat Dagan 和 Omri Ariav 对此工作的贡献。