Skip to content

Commit

Permalink
refactor: extract computeLogNormalScore method (#2710)
Browse files Browse the repository at this point in the history
* refactor: extract computeScore method

* feedback
  • Loading branch information
patrickhulce authored Jul 19, 2017
1 parent 76cdb54 commit 648cce6
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 62 deletions.
24 changes: 24 additions & 0 deletions lighthouse-core/audits/audit.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/
'use strict';

const statistics = require('../lib/statistics');

const DEFAULT_PASS = 'defaultPass';

class Audit {
Expand Down Expand Up @@ -32,6 +34,28 @@ class Audit {
throw new Error('Audit meta information must be overridden.');
}

/**
* Computes a clamped score between 0 and 100 based on the measured value. Score is determined by
* considering a log-normal distribution governed by the two control points, point of diminishing
* returns and the median value, and returning the percentage of sites that have higher value.
*
* @param {number} measuredValue
* @param {number} diminishingReturnsValue
* @param {number} medianValue
* @return {number}
*/
static computeLogNormalScore(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
Expand Down
11 changes: 6 additions & 5 deletions lighthouse-core/audits/byte-efficiency/total-byte-weight.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.computeLogNormalScore(
totalBytes,
SCORING_POINT_OF_DIMINISHING_RETURNS,
SCORING_MEDIAN
);

const headings = [
{key: 'url', itemType: 'url', text: 'URL'},
Expand All @@ -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,
Expand Down
18 changes: 5 additions & 13 deletions lighthouse-core/audits/consistently-interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -234,14 +228,12 @@ 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.computeLogNormalScore(
timeInMs,
SCORING_POINT_OF_DIMINISHING_RETURNS,
SCORING_MEDIAN
),
rawValue: timeInMs,
displayValue: Util.formatMilliseconds(timeInMs),
optimalValue: this.meta.optimalValue,
Expand Down
14 changes: 6 additions & 8 deletions lighthouse-core/audits/dobetterweb/dom-size.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.computeLogNormalScore(
stats.totalDOMNodes,
SCORING_POINT_OF_DIMINISHING_RETURNS,
SCORING_MEDIAN
);

const cards = [{
title: 'Total DOM Nodes',
Expand All @@ -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
Expand Down
11 changes: 6 additions & 5 deletions lighthouse-core/audits/estimated-input-latency.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.computeLogNormalScore(
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),
Expand Down
18 changes: 5 additions & 13 deletions lighthouse-core/audits/first-interactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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.computeLogNormalScore(
firstInteractive.timeInMs,
SCORING_POINT_OF_DIMINISHING_RETURNS,
SCORING_MEDIAN
),
rawValue: firstInteractive.timeInMs,
displayValue: Util.formatMilliseconds(firstInteractive.timeInMs),
extendedInfo: {
Expand Down
15 changes: 6 additions & 9 deletions lighthouse-core/audits/first-meaningful-paint.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.computeLogNormalScore(
firstMeaningfulPaint,
SCORING_POINT_OF_DIMINISHING_RETURNS,
SCORING_MEDIAN
);

return {
score,
duration: firstMeaningfulPaint.toFixed(1),
score: Math.round(score),
rawValue: firstMeaningfulPaint,
extendedInfo
};
Expand Down
15 changes: 6 additions & 9 deletions lighthouse-core/audits/speed-index-metric.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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.computeLogNormalScore(
speedline.perceptualSpeedIndex,
SCORING_POINT_OF_DIMINISHING_RETURNS,
SCORING_MEDIAN
);

const extendedInfo = {
timings: {
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 648cce6

Please sign in to comment.