面试官常问的性能指标计算与优化有哪些...

144 阅读5分钟

from_igvita.png

性能指标对于评估系统的性能表现、发现瓶颈、进行优化和规划资源分配都非常重要。通过监控和分析这些指标,可以及时发现问题、改进系统设计和提供用户满意的性能体验。

性能指标

常见的指标计算与优化

1. FP 白屏(First Paint )-首次渲染时间
const fpTime = performance.getEntriesByType('paint')[0].startTime;
console.log("首次渲染时间:", fpTime, "毫秒");
/**
const whiteScreenTime = performance.timing.responseStart - performance.timing.navigationStart;
console.log("白屏时间:", whiteScreenTime, "毫秒");
*/

优化方案:

  • 使用浏览器缓存和服务端缓存,减少网络请求和下载时间。
  • 压缩和优化资源加载,如图片、CSS 和 JavaScript 文件。
  • 使用合适的文档结构和样式,避免阻塞渲染的操作。
// 优化资源加载,例如使用图片懒加载
// HTML
< img data-src="image.jpg" class="lazy-load-image">

// JavaScript
document.addEventListener('DOMContentLoaded', function() {
  const images = document.querySelectorAll('.lazy-load-image');
  images.forEach(function(image) {
    const src = image.getAttribute('data-src');
    image.setAttribute('src', src);
  });
});
2. FCP 首屏(first contentful paint ) - 首个内容渲染时间
const fcpTime = performance.getEntriesByName('first-contentful-paint')[0].startTime;
console.log("首个内容渲染时间:", fcpTime, "毫秒");

优化方案:

  • 尽早加载和渲染页面关键内容,减少网络请求和处理时间。
  • 延迟加载非关键资源,如图片和脚本,以避免阻塞渲染。
  • 使用合适的图片格式和压缩技术,以减小图片文件的大小。
<!-- 延迟加载脚本 -->
<script defer src="script.js"></script>

<!-- 延迟加载图片 -->
< img src="placeholder.jpg" data-src="image.jpg" class="lazy-load-image">
// JavaScript
document.addEventListener('DOMContentLoaded', function() {
  const images = document.querySelectorAll('.lazy-load-image');
  images.forEach(function(image) {
    const src = image.getAttribute('data-src');
    const img = new Image();
    img.onload = function() {
      image.setAttribute('src', src);
    };
    img.src = src;
  });
});
3. FMP(First Meaningful Paint)- 首个有意义的渲染时间
const fmpTime = performance.getEntriesByType('paint')[1].startTime;
console.log("首个有意义的渲染时间:", fmpTime, "毫秒");

优化方案:

  • 优先加载和渲染页面的核心内容,提高用户感知的加载速度。
<!-- 页面结构 -->
<div id="content">
  <!-- 核心内容 -->
  <h1>优先显示的标题</h1>
  <p>优先显示的段落</p >

  <!-- 其他内容 -->
  <p>延迟加载的段落</p >
  < img src="placeholder.jpg" data-src="image.jpg" class="lazy-load-image">
</div>
// JavaScript
document.addEventListener('DOMContentLoaded', function() {
  // 加载和渲染核心内容
  const content = document.getElementById('content');
  content.style.visibility = 'visible';

  // 延迟加载其他内容
  const lazyImages = document.querySelectorAll('.lazy-load-image');
  lazyImages.forEach(function(image) {
    const src = image.getAttribute('data-src');
    const img = new Image();
    img.onload = function() {
      image.setAttribute('src', src);
    };
    img.src = src;
  });
});
4. TTI(Time to Interactive)- 首次可交互时间
const ttiTime = performance.timing.domInteractive - performance.timing.navigationStart;
console.log("首次可交互时间:", ttiTime, "毫秒");

优化方案:

  • 延迟加载和执行非关键脚本,以提高页面的响应性。
  • 最小化主线程的阻塞,避免长时间的 JavaScript 执行。
  • 使用 Web Worker 将一些计算密集型任务转移到后台线程。
// 延迟加载和执行非关键脚本
<script defer src="non-critical-script.js"></script>
5. TBT(Total Blocking Time)- 总阻塞时间
const tbtTime = performance.getEntriesByName('total-blocking-time')[0].duration;
console.log("总阻塞时间:", tbtTime, "毫秒");

优化方案:

-避免长时间的 JavaScript 执行,尤其是在主线程上。

  • 使用 Web Worker 处理计算密集型任务。
  • 使用 requestIdleCallback() 方法将长时间任务分解为更小的任务,以避免阻塞主线程。
// 使用 requestIdleCallback() 方法将长时间任务分解
function processTask(task) {
  // 处理任务的代码
}

function processTasks(tasks) {
  const batchSize = 10;
  let index = 0;

  function process() {
    const startTime = performance.now();

    while (index < tasks.length && performance.now() - startTime < 16) {
      processTask(tasks[index]);
      index++;
    }

    if (index < tasks.length) {
      requestIdleCallback(process);
    }
  }

  requestIdleCallback(process);
}
document.addEventListener('DOMContentLoaded', function() {
  // 在 DOMContentLoaded 事件触发后调用 processTasks
  processTasks(tasks);
});
/*
window.addEventListener('load', function() {
  // 在页面完全加载后调用 processTasks
  processTasks(tasks);
});
*/
6. CLS(Cumulative Layout Shift)- 累计布局偏移
const clsScore = performance.getEntriesByType('layout-shift')[0].value;
console.log("累计布局偏移:", clsScore);

优化方案:

  • 指定图片和媒体元素的固定宽高,避免内容加载时导致布局偏移。
  • 避免动态插入内容,或者在插入之前为其预留足够的空间。
<!-- 避免内容加载时导致布局偏移 -->
< img src="image.jpg" width="300" height="200">

<!-- 预留足够的空间 -->
<div style="width: 300px; height: 200px;"></div>
7. FPS(Frames per Second)- 每秒帧数
const fps = Math.round(1000 / performance.now());
console.log("每秒帧数:", fps);

优化方案:

  • 减少页面中的复杂动画和过渡效果,以降低渲染负载。
  • 使用 CSS3 的硬件加速技术(如 transform 和 opacity)来优化动画性能。
  • 使用 requestAnimationFrame() 方法来优化动画的更新
// 使用 requestAnimationFrame() 方法来优化动画的更新
function animate() {
  // 更新动画状态

  requestAnimationFrame(animate);
}

// 启动动画
requestAnimationFrame(animate);
8. DCL(DOMContentLoaded)- DOMContentLoaded 事件完成时间
const dclTime = performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart;
console.log("DOMContentLoaded 完成时间:", dclTime, "毫秒");

优化方案:

  • JavaScript 压缩和合并:将多个 JavaScript 文件压缩和合并为一个文件,减少文件的数量和大小,以加快下载和解析的速度。
  • 异步加载脚本:使用 async 或 defer 属性来异步加载 JavaScript 文件,以避免阻塞 DOM 的解析和渲染。
<script async src="script.js"></script>
  • 延迟非关键脚本:将非关键的 JavaScript 脚本标记为延迟加载,以确保页面的主要内容能够更快地呈现给用户。
<script defer src="non-critical-script.js"></script>
  • 避免同步的 CSS:将 CSS 文件放在 head 标签中,并确保不会阻塞 DOM 的解析和渲染。可以使用媒体查询或媒体属性来延迟加载非关键的 CSS。
<link rel="stylesheet" media="print" href="print.css">
  • 图像优化:通过压缩和适当的格式选择来优化图像,以减少其文件大小。

其它指标计算

以下是对每个指标的计算示例:

1. 加载时间(Load Time)
window.addEventListener('load', function() {
  const resourceLoadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
  console.log("资源加载时间:", resourceLoadTime, "毫秒");
});
2. 页面大小(Page Size)
const pageSize = document.documentElement.outerHTML.length;
console.log("页面大小:", pageSize, "字节");
3. 资源请求次数(Resource Requests)
const resourceRequests = performance.getEntriesByType('resource').length;
console.log("资源请求次数:", resourceRequests, "次");
4. 响应时间(Response Time)
const requestStartTime = performance.getEntriesByType('navigation')[0].requestStart;
const responseEndTime = performance.getEntriesByType('navigation')[0].responseEnd;

const responseTime = responseEndTime - requestStartTime;
console.log("响应时间:", responseTime, "毫秒");
5. DOM 完全加载时间(DOMContentLoaded)
window.addEventListener('DOMContentLoaded', function() {
  const domContentLoadedTime = performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart;
  console.log("DOM 完全加载时间:", domContentLoadedTime, "毫秒");
});
6. 页面渲染时间(Page Render Time)
window.addEventListener('load', function() {
  const renderTime = performance.timing.loadEventEnd - performance.timing.responseEnd;
  console.log("页面渲染时间:", renderTime, "毫秒");
});
7. 页面卸载时间(Page Unload Time)
window.addEventListener('unload', function() {
  const unloadTime = performance.timing.unloadEventEnd - performance.timing.unloadEventStart;
  console.log("页面卸载时间:", unloadTime, "毫秒");
});

在实际应用中,可以使用浏览器开发者工具、性能测试工具和在线监测工具来测量这些指标,并根据结果进行优化。保持学习,共勉~