From f0909fce56969ea84bbd477e902cf936df3708d4 Mon Sep 17 00:00:00 2001 From: Patrick Hulce Date: Tue, 18 Jul 2017 16:12:07 -0700 Subject: [PATCH] refactor: extract computeScore method --- lighthouse-core/audits/audit.js | 23 +++++++++++++++++++ .../byte-efficiency/total-byte-weight.js | 11 +++++---- .../audits/consistently-interactive.js | 14 +---------- .../audits/dobetterweb/dom-size.js | 14 +++++------ .../audits/estimated-input-latency.js | 11 +++++---- lighthouse-core/audits/first-interactive.js | 18 ++++----------- .../audits/first-meaningful-paint.js | 15 +++++------- lighthouse-core/audits/speed-index-metric.js | 15 +++++------- 8 files changed, 59 insertions(+), 62 deletions(-) diff --git a/lighthouse-core/audits/audit.js b/lighthouse-core/audits/audit.js index b0b2361484eb..ad2c47215a9a 100644 --- a/lighthouse-core/audits/audit.js +++ b/lighthouse-core/audits/audit.js @@ -5,6 +5,8 @@ */ 'use strict'; +const statistics = require('../lib/statistics'); + const DEFAULT_PASS = 'defaultPass'; class Audit { @@ -32,6 +34,27 @@ class Audit { throw new Error('Audit meta information must be overridden.'); } + /** + * Computes and clamps the score between 0 and 100 based on the measured value, and the two control + * points on the log-normal distribution (point of diminishing returns and the median value). + * + * @param {number} measuredValue + * @param {number} diminishingReturnsValue + * @param {number} medianValue + * @return {number} + */ + static computeScore(measuredValue, diminishingReturnsValue, medianValue) { + const distribution = statistics.getLogNormalDistribution( + medianValue, + diminishingReturnsValue + ); + + let score = 100 * distribution.computeComplementaryPercentile(measuredValue); + score = Math.min(100, score); + score = Math.max(0, score); + return Math.round(score); + } + /** * @param {!Audit} audit * @param {string} debugString diff --git a/lighthouse-core/audits/byte-efficiency/total-byte-weight.js b/lighthouse-core/audits/byte-efficiency/total-byte-weight.js index fe60a89ad11a..1441406301ab 100644 --- a/lighthouse-core/audits/byte-efficiency/total-byte-weight.js +++ b/lighthouse-core/audits/byte-efficiency/total-byte-weight.js @@ -9,7 +9,6 @@ 'use strict'; const ByteEfficiencyAudit = require('./byte-efficiency-audit'); -const statistics = require('../../lib/statistics'); // Parameters for log-normal CDF scoring. See https://www.desmos.com/calculator/gpmjeykbwr // ~75th and ~90th percentiles http://httparchive.org/interesting.php?a=All&l=Feb%201%202017&s=All#bytesTotal @@ -72,9 +71,11 @@ class TotalByteWeight extends ByteEfficiencyAudit { // <= 1600KB: score≈100 // 4000KB: score=50 // >= 9000KB: score≈0 - const distribution = statistics.getLogNormalDistribution( - SCORING_MEDIAN, SCORING_POINT_OF_DIMINISHING_RETURNS); - const score = 100 * distribution.computeComplementaryPercentile(totalBytes); + const score = ByteEfficiencyAudit.computeScore( + totalBytes, + SCORING_POINT_OF_DIMINISHING_RETURNS, + SCORING_MEDIAN + ); const headings = [ {key: 'url', itemType: 'url', text: 'URL'}, @@ -85,10 +86,10 @@ class TotalByteWeight extends ByteEfficiencyAudit { const tableDetails = ByteEfficiencyAudit.makeTableDetails(headings, results); return { + score, rawValue: totalBytes, optimalValue: this.meta.optimalValue, displayValue: `Total size was ${ByteEfficiencyAudit.bytesToKbString(totalBytes)}`, - score: Math.round(Math.max(0, Math.min(score, 100))), extendedInfo: { value: { results, diff --git a/lighthouse-core/audits/consistently-interactive.js b/lighthouse-core/audits/consistently-interactive.js index 02905bedbf5e..8071f7c1ace0 100644 --- a/lighthouse-core/audits/consistently-interactive.js +++ b/lighthouse-core/audits/consistently-interactive.js @@ -8,7 +8,6 @@ const Audit = require('./audit'); const Util = require('../report/v2/renderer/util.js'); const TracingProcessor = require('../lib/traces/tracing-processor'); -const statistics = require('../lib/statistics'); // Parameters (in ms) for log-normal CDF scoring. To see the curve: // https://www.desmos.com/calculator/uti67afozh @@ -19,11 +18,6 @@ const REQUIRED_QUIET_WINDOW = 5000; const ALLOWED_CONCURRENT_REQUESTS = 2; const IGNORED_NETWORK_SCHEMES = ['data', 'ws']; -const distribution = statistics.getLogNormalDistribution( - SCORING_MEDIAN, - SCORING_POINT_OF_DIMINISHING_RETURNS -); - /** * @fileoverview This audit identifies the time the page is "consistently interactive". * Looks for the first period of at least 5 seconds after FMP where both CPU and network were quiet, @@ -234,14 +228,8 @@ class ConsistentlyInteractiveMetric extends Audit { const timeInMs = (timestamp - traceOfTab.timestamps.navigationStart) / 1000; const extendedInfo = Object.assign(quietPeriodInfo, {timestamp, timeInMs}); - let score = 100 * distribution.computeComplementaryPercentile(timeInMs); - // Clamp the score to 0 <= x <= 100. - score = Math.min(100, score); - score = Math.max(0, score); - score = Math.round(score); - return { - score, + score: Audit.computeScore(timeInMs, SCORING_POINT_OF_DIMINISHING_RETURNS, SCORING_MEDIAN), rawValue: timeInMs, displayValue: Util.formatMilliseconds(timeInMs), optimalValue: this.meta.optimalValue, diff --git a/lighthouse-core/audits/dobetterweb/dom-size.js b/lighthouse-core/audits/dobetterweb/dom-size.js index 5d10e8d1c25f..546c662d277e 100644 --- a/lighthouse-core/audits/dobetterweb/dom-size.js +++ b/lighthouse-core/audits/dobetterweb/dom-size.js @@ -13,7 +13,6 @@ 'use strict'; const Audit = require('../audit'); -const statistics = require('../../lib/statistics'); const Util = require('../../report/v2/renderer/util.js'); const MAX_DOM_NODES = 1500; @@ -73,12 +72,11 @@ class DOMSize extends Audit { // <= 1500: score≈100 // 3000: score=50 // >= 5970: score≈0 - const distribution = statistics.getLogNormalDistribution( - SCORING_MEDIAN, SCORING_POINT_OF_DIMINISHING_RETURNS); - let score = 100 * distribution.computeComplementaryPercentile(stats.totalDOMNodes); - - // Clamp the score to 0 <= x <= 100. - score = Math.max(0, Math.min(100, score)); + const score = Audit.computeScore( + stats.totalDOMNodes, + SCORING_POINT_OF_DIMINISHING_RETURNS, + SCORING_MEDIAN + ); const cards = [{ title: 'Total DOM Nodes', @@ -97,9 +95,9 @@ class DOMSize extends Audit { }]; return { + score, rawValue: stats.totalDOMNodes, optimalValue: this.meta.optimalValue, - score: Math.round(score), displayValue: `${Util.formatNumber(stats.totalDOMNodes)} nodes`, extendedInfo: { value: cards diff --git a/lighthouse-core/audits/estimated-input-latency.js b/lighthouse-core/audits/estimated-input-latency.js index a729cf6d7a28..4d8c430b26dd 100644 --- a/lighthouse-core/audits/estimated-input-latency.js +++ b/lighthouse-core/audits/estimated-input-latency.js @@ -8,7 +8,6 @@ const Audit = require('./audit'); const Util = require('../report/v2/renderer/util.js'); const TracingProcessor = require('../lib/traces/tracing-processor'); -const statistics = require('../lib/statistics'); // Parameters (in ms) for log-normal CDF scoring. To see the curve: // https://www.desmos.com/calculator/srv0hqhf7d @@ -51,12 +50,14 @@ class EstimatedInputLatency extends Audit { // Median = 100ms // 75th Percentile ≈ 133ms // 95th Percentile ≈ 199ms - const distribution = statistics.getLogNormalDistribution(SCORING_MEDIAN, - SCORING_POINT_OF_DIMINISHING_RETURNS); - const score = 100 * distribution.computeComplementaryPercentile(ninetieth.time); + const score = Audit.computeScore( + ninetieth.time, + SCORING_POINT_OF_DIMINISHING_RETURNS, + SCORING_MEDIAN + ); return { - score: Math.round(score), + score, optimalValue: EstimatedInputLatency.meta.optimalValue, rawValue, displayValue: Util.formatMilliseconds(rawValue, 1), diff --git a/lighthouse-core/audits/first-interactive.js b/lighthouse-core/audits/first-interactive.js index 64c4d52d443d..cbeb44c17da1 100644 --- a/lighthouse-core/audits/first-interactive.js +++ b/lighthouse-core/audits/first-interactive.js @@ -7,18 +7,12 @@ const Audit = require('./audit'); const Util = require('../report/v2/renderer/util.js'); -const statistics = require('../lib/statistics'); // Parameters (in ms) for log-normal CDF scoring. To see the curve: // https://www.desmos.com/calculator/rjp0lbit8y const SCORING_POINT_OF_DIMINISHING_RETURNS = 1700; const SCORING_MEDIAN = 10000; -const distribution = statistics.getLogNormalDistribution( - SCORING_MEDIAN, - SCORING_POINT_OF_DIMINISHING_RETURNS -); - class FirstInteractiveMetric extends Audit { /** * @return {!AuditMeta} @@ -46,14 +40,12 @@ class FirstInteractiveMetric extends Audit { const trace = artifacts.traces[Audit.DEFAULT_PASS]; return artifacts.requestFirstInteractive(trace) .then(firstInteractive => { - let score = 100 * distribution.computeComplementaryPercentile(firstInteractive.timeInMs); - // Clamp the score to 0 <= x <= 100. - score = Math.min(100, score); - score = Math.max(0, score); - score = Math.round(score); - return { - score, + score: Audit.computeScore( + firstInteractive.timeInMs, + SCORING_POINT_OF_DIMINISHING_RETURNS, + SCORING_MEDIAN + ), rawValue: firstInteractive.timeInMs, displayValue: Util.formatMilliseconds(firstInteractive.timeInMs), extendedInfo: { diff --git a/lighthouse-core/audits/first-meaningful-paint.js b/lighthouse-core/audits/first-meaningful-paint.js index 09012572e109..4f26ba7a6123 100644 --- a/lighthouse-core/audits/first-meaningful-paint.js +++ b/lighthouse-core/audits/first-meaningful-paint.js @@ -7,7 +7,6 @@ const Audit = require('./audit'); const Util = require('../report/v2/renderer/util.js'); -const statistics = require('../lib/statistics'); // Parameters (in ms) for log-normal CDF scoring. To see the curve: // https://www.desmos.com/calculator/joz3pqttdq @@ -101,17 +100,15 @@ class FirstMeaningfulPaint extends Audit { // 4000ms: score=50 // >= 14000ms: score≈0 const firstMeaningfulPaint = traceOfTab.timings.firstMeaningfulPaint; - const distribution = statistics.getLogNormalDistribution(SCORING_MEDIAN, - SCORING_POINT_OF_DIMINISHING_RETURNS); - let score = 100 * distribution.computeComplementaryPercentile(firstMeaningfulPaint); - - // Clamp the score to 0 <= x <= 100. - score = Math.min(100, score); - score = Math.max(0, score); + const score = Audit.computeScore( + firstMeaningfulPaint, + SCORING_POINT_OF_DIMINISHING_RETURNS, + SCORING_MEDIAN + ); return { + score, duration: firstMeaningfulPaint.toFixed(1), - score: Math.round(score), rawValue: firstMeaningfulPaint, extendedInfo }; diff --git a/lighthouse-core/audits/speed-index-metric.js b/lighthouse-core/audits/speed-index-metric.js index af37677c569c..61b003fc5315 100644 --- a/lighthouse-core/audits/speed-index-metric.js +++ b/lighthouse-core/audits/speed-index-metric.js @@ -6,7 +6,6 @@ 'use strict'; const Audit = require('./audit'); -const statistics = require('../lib/statistics'); const Util = require('../report/v2/renderer/util'); // Parameters (in ms) for log-normal CDF scoring. To see the curve: @@ -63,13 +62,11 @@ class SpeedIndexMetric extends Audit { // Median = 5,500 // 75th Percentile = 8,820 // 95th Percentile = 17,400 - const distribution = statistics.getLogNormalDistribution(SCORING_MEDIAN, - SCORING_POINT_OF_DIMINISHING_RETURNS); - let score = 100 * distribution.computeComplementaryPercentile(speedline.perceptualSpeedIndex); - - // Clamp the score to 0 <= x <= 100. - score = Math.min(100, score); - score = Math.max(0, score); + const score = Audit.computeScore( + speedline.perceptualSpeedIndex, + SCORING_POINT_OF_DIMINISHING_RETURNS, + SCORING_MEDIAN + ); const extendedInfo = { timings: { @@ -97,7 +94,7 @@ class SpeedIndexMetric extends Audit { const rawValue = Math.round(speedline.perceptualSpeedIndex); return { - score: Math.round(score), + score, rawValue, displayValue: Util.formatNumber(rawValue), optimalValue: this.meta.optimalValue,