Performance.now
Performance는 프론트엔드 성능 모니터링에 꼭 필요한 API입니다. 페이지가 완전히 로드된 후에는 많은 값을 얻어야 하기 때문에 페이지가 완전히 로드된 후에 사용하는 것이 가장 좋습니다. 가장 간단한 방법은 window.onload 이벤트에서 다양한 데이터를 읽는 것입니다.
performance.now() 메서드는 밀리초 단위의 정확한 DOMHighResTimeStamp를 반환합니다.
MDN에 따르면:
이 타임스탬프는 실제로 매우 정확하지 않습니다. Spectre와 같은 보안 위협을 줄이기 위해 다양한 브라우저는 이 유형의 가치를 다양한 수준으로 마무리합니다. (Firefox는 Firefox 59부터 2밀리초 정밀도로 반올림됩니다.) 일부 브라우저에서는 이 값을 약간 무작위화할 수도 있습니다. 이 값의 정확성은 향후 버전에서 다시 향상될 수 있습니다. 브라우저 개발자는 이러한 타이밍 공격과 이를 더 효과적으로 완화하는 방법을 계속 조사하고 있습니다.
함수 실행 시간을 계산하려면 아래와 같이 함수 실행 전과 후의performance.now()값을 두 번 비교하면 됩니다.
const t0 = performance.now(); for (let i = 0; iFirefox와 Chrome을 관찰할 수 있습니다. 여기에 제시된 결과는 완전히 다릅니다. 이는 버전 60부터 Firefox가 성능 API의 정밀도를 2ms로 낮추기 때문입니다.
성능 API는 타임스탬프를 반환할 뿐만 아니라 필요에 따라 MDN으로 이동하여 관련 문서를 쿼리할 수 있는 많은 실용적인 방법을 제공합니다.
그러나 우리의 사용 사례에서는 단일 함수의 성능만 계산하려고 하므로 타임스탬프이면 충분합니다.
performance.now()는 Date.now와 동일합니까?
Date.now로도 그렇게 할 수 있다고 생각하실 수도 있습니다.
예, 가능하지만 단점이 있습니다.
Date.now는 Unix 시대(1970-01-01T00:00:00Z) 이후 경과된 시간을 밀리초 단위로 반환하며 시스템 시계에 따라 다릅니다. 이는 충분히 정확하지 않다는 의미일 뿐만 아니라 항상 증분적인 것도 아닙니다. 여기서 WebKit 엔지니어 Tony Gentilcore는 다음과 같이 설명합니다.
시스템 시간을 날짜로 사용하는 것은 최선의 선택이 아닐 수도 있고 사용자 모니터링에 적합하지도 않습니다. 대부분의 시스템은 주기적으로 시간을 동기화하는 데몬을 실행합니다. 일반적으로 시계는 15~20분마다 몇 밀리초씩 조정됩니다. 이 속도에서는 10초 간격 중 약 1%가 부정확합니다.
Performance.mark 및 Performance.measure
Performance.now 기능 외에도 코드의 다양한 부분의 시간을 측정하고 이를 성능 테스트 도구에서 사용자 정의 측정항목으로 사용할 수 있는 기능도 있습니다. 웹페이지테스트로.
Performance.mark
먼저 MDN의 mark 메소드 정의를 살펴보겠습니다.
mark() 메소드는 주어진 이름으로 브라우저의 성능 항목 버퍼에 타임스탬프를 생성합니다.
이 단락의 단어는 세 가지 핵심 단어로 나눌 수 있습니다. 첫 번째 타임스탬프, 여기서 타임스탬프는 고정밀 타임스탬프(1000분의 1밀리초)를 의미하고 그 다음에는 성능 항목 버퍼가 따릅니다.
성능 항목 버퍼는 성능 인스턴스 개체가 저장되는 영역을 말하며 초기 값은 비어 있습니다.
마지막 이름은 생성된 각 타임스탬프에 해당하는 이름이 있다는 의미입니다.
그러므로 이 문장은 브라우저의 성능 항목 버퍼에 있는 이름을 기반으로 고정밀 타임스탬프를 생성하는 것으로 이해될 수 있습니다. 이것이 바로 많은 사람들이 **"경영"**이라고 부르는 것입니다.
Performance.now와 마찬가지로 이 기능의 정밀도 점수는 최대 5μs입니다.
performance.mark('name');
마크에 대한 성능 항목에는 다음 속성 값이 있습니다.
entryType - "mark"로 설정
name - 마크가 생성될 때 제공된 "name"으로 설정
startTime - set mark() 메소드가 호출될 때의 타임스탬프입니다.
duration - "0"으로 설정합니다(표시에는 지속 시간이 없음).
Performance.measure
또한 MDN의 측정 정의를 살펴보겠습니다.
이 정의는 동일합니다. 위의 마크와 같이 정의는 다소 유사하며, 핵심적인 차이점은 지정된 두 마크 사이의 문장에 있습니다. 따라서 측정값은 두 마크 포인트 사이의 타임스탬프를 지정합니다. 표시가 '점'으로 이해된다면 측정은 '연결'로 이해될 수 있습니다.
performance.measure(name, startMark, endMark);
두 마크 사이의 시간을 계산하고 DOMHighResTimeStamp를 생성한 후 이를 성능.getEntries()와 같은 관련 인터페이스를 통해 얻을 수 있는 리소스 캐시 데이터에 저장합니다.
entryType은 문자열 측정값입니다.
name은 생성 시 설정된 값입니다.
startTime은 측정값이 호출되는 시간입니다.
duration은 탐색에서 두 표시 사이의 지속 시간
입니다. 측정 시작
performance.measure('measure name');
탐색 시작
performance.measure('measure name', undefined, 'mark-2');
표시에서 표시까지
performance.measure('measure name', 'mark-1', 'mark-2');
리소스 성능 데이터
성능 항목 버퍼에서 데이터 가져오기
在上面的函数中,总是提到结果存储在performance entry buffer,但是如何访问其中的内容呢?
performance API有3个函数可以用来访问该数据:
performance.getEntries()
获取一组当前页面已经加载的资源PerformanceEntry对象。接收一个可选的参数options进行过滤,options支持的属性有name,entryType,initiatorType。
let entries = window.performance.getEntries();
performance.getEntriesByName
根据参数name,type获取一组当前页面已经加载的资源数据。资源数据中的"name"字段对应于"name"的取值,资源数据中的"entryType"字段对应于"type"的取值。
let entries = window.performance.getEntriesByName(name, type);
performance.getEntriesByType
根据参数type获取一组当前页面已经加载的资源数据。type取值对应到资源数据中的entryType字段。
var entries = window.performance.getEntriesByType(type);
结合事例:
performance.mark('mark-1'); // some code performance.mark('mark-2') performance.measure('test', 'mark-1', 'mark-2') console.log(performance.getEntriesByName('test')[0].duration);
Console.time
这个 API确实易于使用。当需要统计一段代码的执行时间时,可以使用console.time方法与console.timeEnd方法,其中console.time方法用于标记开始时间,console.timeEnd方法用于标记结束时间,并且将结束时间与开始时间之间经过的毫秒数在控制台中输出。这两个方法的使用方法如下所示。
console.time('test'); for (let i = 0; i输出的结果与Performance API非常相似。
console.time的优点是易于使用,因为它不需要手动计算两个时间戳之间的差。
减少时间精度
如果在不同的浏览器中使用上面提到的 api 测量函数,你可能会注意到结果是不同的。
这是由于浏览器试图保护用户免受时序攻击(timing attack)和指纹采集(Fingerprinting ),如果时间戳过于准确,黑客可以使用它们来识别用户。
例如,Firefox等浏览器试图通过将精度降低到2ms(版本60)来防止这种情况发生。
注意事项
现在,我们已经知道了要测量JavaScript函数的速度所需方法。但是,最好还要避免一些陷阱:
分而治之
开发过程中,我们可能会我发现有些模块执行速度很慢,但是我们不知道具体问题出在哪里。一种解决方案是使用前面提到的这些函数来测量代码,而不是随便猜测哪一部分比较慢。
为了跟踪它,你需要在执行速度较慢的代码块周围放置console.time语句。然后测量它们不同部分的表现。如果一个比另一个慢,那就继续往下走,直到发现问题所在。
注意输入值
在实际应用中,给定函数的输入值可能会发生很大变化。我们无法通过仅针对任意随机值测量函数的速度来获得任何实用的有价值数据。
确保使用相同的输入值运行代码。
多次运行该函数
如果你拥有一个函数,它的功能在于遍历一个数组,在对数组的每个值执行一些计算后,返回一个包含计算结果的新数组。你想知道是forEach循环还是简单的for循环性能更好。
function testForEach(x) { console.time('test-forEach'); const res = []; x.forEach((value, index) => { res.push(value / 1.2 * 0.1); }); console.timeEnd('test-forEach') return res; } function testFor(x) { console.time('test-for'); const res = []; for (let i = 0; i然后这样测试它们:
const x = new Array(100000).fill(Math.random()); testForEach(x); testFor(x);로그인 후 복사
如果在 Firefox 中运行上述函数,结果:
看起来forEach慢多了,对吧?
那如果是相同的输入,运行两次呢:
testForEach(x); testForEach(x); testFor(x); testFor(x);
在第二次调用forEach的情况下,其执行效果应该是和使用for循环相同。考虑到初始值较慢,在一些性能要求极高的项目,可能就不适合使用forEach。
在多个浏览器中测试
如果我们在Chrome中运行上述代码,结果又会不一样:
这是因为Chrome和Firefox具有不同的JavaScript引擎,它们具有不同类型的性能优化。
在本例中,Firefox 在对相同输入的forEach进行优化方面做得更好。
for在两个引擎上的性能都更好,因此在一些性能要求极高的项目就需要使用for循环。
这是为什么要在多个引擎中进行测量的一个很好的例子。只使用Chrome作为度量标准可能导致你得出结论,forEach与for相比并不那么糟糕。
限制的 CPU
在本地测试时得到的结果不代表用户在浏览器中的使用情况,因为我们开发者使用的电脑通常比大多数用户的电脑配置更好。
브라우저에는 CPU 성능을 제한하는 기능이 있어 보다 현실적으로 설정할 수 있습니다.
위 내용은 성능을 사용하여 프런트엔드 성능을 모니터링하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!