Improve bench
This commit is contained in:
parent
2e4015de40
commit
7d5ba5033b
|
@ -19,8 +19,7 @@ A Rust HTML minifier meticulously optimised for speed and effectiveness, with bi
|
||||||
|
|
||||||
Comparison with [html-minfier](https://github.com/kangax/html-minifier) and [minimize](https://github.com/Swaagie/minimize), run on the top web pages. [See the breakdown here.](./bench)
|
Comparison with [html-minfier](https://github.com/kangax/html-minifier) and [minimize](https://github.com/Swaagie/minimize), run on the top web pages. [See the breakdown here.](./bench)
|
||||||
|
|
||||||
<img width="415" alt="Chart showing speed of HTML minifiers" src="https://wilsonl.in/minify-html/bench/0.6.1/core/average-speeds.png">
|
<img width="415" alt="Chart showing speed of HTML minifiers" src="https://wilsonl.in/minify-html/bench/0.6.1/core/average-speeds.png"><img width="415" alt="Chart showing compression of HTML minifiers" src="https://wilsonl.in/minify-html/bench/0.6.1/core/average-sizes.png">
|
||||||
<img width="415" alt="Chart showing compression of HTML minifiers" src="https://wilsonl.in/minify-html/bench/0.6.1/core/average-sizes.png">
|
|
||||||
|
|
||||||
The [onepass](https://github.com/wilsonzlin/minify-html/tree/master/rust/onepass) variant is even more optimised for speed. See its [README](https://github.com/wilsonzlin/minify-html/tree/master/rust/onepass) for more details.
|
The [onepass](https://github.com/wilsonzlin/minify-html/tree/master/rust/onepass) variant is even more optimised for speed. See its [README](https://github.com/wilsonzlin/minify-html/tree/master/rust/onepass) for more details.
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,7 @@ It also contains a set of common web pages as tests for benchmarking.
|
||||||
|
|
||||||
## Comparison
|
## Comparison
|
||||||
|
|
||||||
The [Node.js version of minify-html](../nodejs) is tested against [html-minfier](https://github.com/kangax/html-minifier) and [minimize](https://github.com/Swaagie/minimize) in two dimensions:
|
Each minifier is run against each file in the [inputs](./inputs) folder, which are HTML pages fetched from popular websites:
|
||||||
|
|
||||||
- Speed as operations per second.
|
|
||||||
- Minified file size compared to the original.
|
|
||||||
|
|
||||||
[Benchmark.js](https://benchmarkjs.com) is used to determine speed. Each minifier is run against each file in the [tests](./tests) folder, which are HTML pages fetched from popular websites:
|
|
||||||
|
|
||||||
|File name|URL|
|
|File name|URL|
|
||||||
|---|---|
|
|---|---|
|
||||||
|
@ -35,37 +30,14 @@ For more information on how the tests are fetched, see [fetch.js](./fetch.js).
|
||||||
|
|
||||||
On this [project's README](../README.md), average graphs are shown. Graphs showing per-test results are shown below:
|
On this [project's README](../README.md), average graphs are shown. Graphs showing per-test results are shown below:
|
||||||
|
|
||||||
<img width="435" alt="Chart showing speed of HTML minifiers per test" src="https://wilsonl.in/minify-html/bench/0.6.1/core/speeds.png"> <img width="435" alt="Chart showing effectiveness of HTML minifiers per test" src="https://wilsonl.in/minify-html/bench/0.6.1/core/sizes.png">
|
<img width="435" alt="Chart showing speed of HTML minifiers per test" src="https://wilsonl.in/minify-html/bench/0.6.1/core/speeds.png"><img width="435" alt="Chart showing effectiveness of HTML minifiers per test" src="https://wilsonl.in/minify-html/bench/0.6.1/core/sizes.png">
|
||||||
|
|
||||||
Since speed depends on the input, speed charts show performance relative to the Node.js minify-html as a percentage.
|
Results depend on the input, so charts show performance relative to minify-html as a percentage.
|
||||||
|
|
||||||
The settings used for each minifier can be found in [minifiers.js](./minifiers.js). Some settings to note:
|
|
||||||
|
|
||||||
- `conservativeCollapse` is enabled for html-minifier as otherwise some whitespace would be unsafely removed with side effects. minify-html can safely remove whitespace with context if configured properly.
|
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
Make sure to install the dependencies listed in [package.json](./package.json) by running `npm i` or `yarn`.
|
Run [build](./build) to build the minifiers.
|
||||||
|
|
||||||
Run [build.sh](./build.sh) to build @minify-html/js with the local minify-html.
|
Run [run](./run) to benchmark the performance of each HTML minifier against each test and record the op/s results.
|
||||||
|
|
||||||
Run [sizes.js](sizes.js) to run each HTML minifier against each test and record the minified size results. This will also output the minified files in `min` if inspection of minified outputs is necessary. [compare.sh](./compare.sh) is a useful script for viewing a character-by-character diff between the minified outputs of minify-html and html-minifier for a specific test. Pass the test's file name as the first argument.
|
|
||||||
|
|
||||||
Run [speeds.js](./speeds.js) to benchmark the performance of each HTML minifier against each test and record the op/s results.
|
|
||||||
|
|
||||||
Run [graph.js](./graph.js) to render graphs from recorded speed and size results in the `results` folder.
|
Run [graph.js](./graph.js) to render graphs from recorded speed and size results in the `results` folder.
|
||||||
|
|
||||||
## minify-html-bench
|
|
||||||
|
|
||||||
The [minify-html-bench](./minify-html-bench) folder contains a Rust executable subproject that runs the local minify-html on all tests for many iterations to calculate speed as operations per second.
|
|
||||||
|
|
||||||
This can be useful for profiling the core code or checking the performance of minify-html in other languages with native bindings.
|
|
||||||
|
|
||||||
It takes two arguments:
|
|
||||||
|
|
||||||
- `--tests`: path to the folder containing tests to use as inputs.
|
|
||||||
- `--iterations`: how many iterations to run per test.
|
|
||||||
|
|
||||||
The results will be written to stdout as a JSON object, where properties are the test file names and values are the operations per second.
|
|
||||||
|
|
||||||
Profiling minify-html can be done on Linux by using [profile.sh](./profile.sh), which uses `perf`. The generated report can be used using `perf report`.
|
|
||||||
|
|
120
bench/graph.js
120
bench/graph.js
|
@ -1,7 +1,7 @@
|
||||||
const results = require("./results");
|
const fs = require("fs/promises");
|
||||||
const https = require("https");
|
const https = require("https");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs/promises");
|
const results = require("./results");
|
||||||
|
|
||||||
const GRAPHS_DIR = path.join(__dirname, "graphs");
|
const GRAPHS_DIR = path.join(__dirname, "graphs");
|
||||||
const SPEEDS_GRAPH = path.join(GRAPHS_DIR, "speeds.png");
|
const SPEEDS_GRAPH = path.join(GRAPHS_DIR, "speeds.png");
|
||||||
|
@ -10,7 +10,6 @@ const AVERAGE_SPEEDS_GRAPH = path.join(GRAPHS_DIR, "average-speeds.png");
|
||||||
const AVERAGE_SIZES_GRAPH = path.join(GRAPHS_DIR, "average-sizes.png");
|
const AVERAGE_SIZES_GRAPH = path.join(GRAPHS_DIR, "average-sizes.png");
|
||||||
|
|
||||||
const speedColours = {
|
const speedColours = {
|
||||||
"@minify-html/js": "#2e61bd",
|
|
||||||
"minify-html": "#2e61bd",
|
"minify-html": "#2e61bd",
|
||||||
"minify-html-onepass": "#222",
|
"minify-html-onepass": "#222",
|
||||||
};
|
};
|
||||||
|
@ -21,12 +20,57 @@ const sizeColours = {
|
||||||
};
|
};
|
||||||
const defaultSizeColour = "rgb(188, 188, 188)";
|
const defaultSizeColour = "rgb(188, 188, 188)";
|
||||||
|
|
||||||
|
const averageChartOptions = (label) => ({
|
||||||
|
options: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
xAxes: [
|
||||||
|
{
|
||||||
|
barPercentage: 0.5,
|
||||||
|
gridLines: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
fontColor: "#555",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
type: "linear",
|
||||||
|
scaleLabel: {
|
||||||
|
display: true,
|
||||||
|
fontColor: '#222',
|
||||||
|
fontSize: 24,
|
||||||
|
fontStyle: "bold",
|
||||||
|
labelString: label,
|
||||||
|
padding: 12,
|
||||||
|
},
|
||||||
|
position: "left",
|
||||||
|
ticks: {
|
||||||
|
callback: "$$$_____REPLACE_WITH_TICK_CALLBACK_____$$$",
|
||||||
|
fontColor: "#222",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
color: "#eee",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const breakdownChartOptions = (title) => ({
|
const breakdownChartOptions = (title) => ({
|
||||||
options: {
|
options: {
|
||||||
legend: {
|
legend: {
|
||||||
display: true,
|
display: true,
|
||||||
labels: {
|
labels: {
|
||||||
fontColor: "#000",
|
fontColor: "#000",
|
||||||
|
fontSize: 20,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
|
@ -64,52 +108,6 @@ const breakdownChartOptions = (title) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const axisLabel = (fontColor, labelString) => ({
|
|
||||||
display: true,
|
|
||||||
fontColor,
|
|
||||||
fontSize: 24,
|
|
||||||
fontStyle: "bold",
|
|
||||||
labelString,
|
|
||||||
padding: 12,
|
|
||||||
});
|
|
||||||
|
|
||||||
const averageChartOptions = (label) => ({
|
|
||||||
options: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
xAxes: [
|
|
||||||
{
|
|
||||||
barPercentage: 0.5,
|
|
||||||
gridLines: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
fontColor: "#555",
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
yAxes: [
|
|
||||||
{
|
|
||||||
type: "linear",
|
|
||||||
scaleLabel: axisLabel("#222", label),
|
|
||||||
position: "left",
|
|
||||||
ticks: {
|
|
||||||
callback: "$$$_____REPLACE_WITH_TICK_CALLBACK_____$$$",
|
|
||||||
fontColor: "#222",
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
gridLines: {
|
|
||||||
color: "#eee",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const renderChart = (cfg, width, height) =>
|
const renderChart = (cfg, width, height) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const req = https.request("https://quickchart.io/chart", {
|
const req = https.request("https://quickchart.io/chart", {
|
||||||
|
@ -147,9 +145,7 @@ const renderChart = (cfg, width, height) =>
|
||||||
await fs.mkdir(GRAPHS_DIR, { recursive: true });
|
await fs.mkdir(GRAPHS_DIR, { recursive: true });
|
||||||
|
|
||||||
const res = results.calculate();
|
const res = results.calculate();
|
||||||
const speedMinifiers = [...res.minifiers].sort(
|
const speedMinifiers = ["html-minifier", "minimize", "minify-html", "minify-html-onepass"];
|
||||||
(a, b) => res.minifierAvgOps[a] - res.minifierAvgOps[b]
|
|
||||||
);
|
|
||||||
const sizeMinifiers = ["minimize", "html-minifier", "minify-html"];
|
const sizeMinifiers = ["minimize", "html-minifier", "minify-html"];
|
||||||
const inputs = Object.keys(res.inputSizes).sort();
|
const inputs = Object.keys(res.inputSizes).sort();
|
||||||
|
|
||||||
|
@ -159,7 +155,7 @@ const renderChart = (cfg, width, height) =>
|
||||||
{
|
{
|
||||||
type: "bar",
|
type: "bar",
|
||||||
data: {
|
data: {
|
||||||
labels: speedMinifiers.map((m) => m.replace(" (", "\n(")),
|
labels: speedMinifiers,
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
backgroundColor: speedMinifiers.map(
|
backgroundColor: speedMinifiers.map(
|
||||||
|
@ -184,7 +180,7 @@ const renderChart = (cfg, width, height) =>
|
||||||
{
|
{
|
||||||
type: "bar",
|
type: "bar",
|
||||||
data: {
|
data: {
|
||||||
labels: sizeMinifiers.map((m) => m.replace(" (", "\n(")),
|
labels: sizeMinifiers,
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
backgroundColor: sizeMinifiers.map(
|
backgroundColor: sizeMinifiers.map(
|
||||||
|
@ -212,14 +208,14 @@ const renderChart = (cfg, width, height) =>
|
||||||
label: minifier,
|
label: minifier,
|
||||||
data: inputs.map(
|
data: inputs.map(
|
||||||
(input) =>
|
(input) =>
|
||||||
res.perInputOps[minifier][input] / res.maxInputOps[input]
|
res.perInputOps[minifier][input] / res.perInputOps['minify-html'][input]
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
...breakdownChartOptions("Operations per second (higher is better)"),
|
...breakdownChartOptions("Operations per second, relative to minify-html"),
|
||||||
},
|
},
|
||||||
900,
|
800,
|
||||||
1000
|
1280
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -232,13 +228,13 @@ const renderChart = (cfg, width, height) =>
|
||||||
labels: inputs,
|
labels: inputs,
|
||||||
datasets: sizeMinifiers.map((minifier) => ({
|
datasets: sizeMinifiers.map((minifier) => ({
|
||||||
label: minifier,
|
label: minifier,
|
||||||
data: inputs.map((input) => res.perInputReduction[minifier][input]),
|
data: inputs.map((input) => res.perInputReduction[minifier][input] / res.perInputReduction['minify-html'][input]),
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
...breakdownChartOptions("Size reduction (higher is better)"),
|
...breakdownChartOptions("Size reduction, relative to minify-html"),
|
||||||
},
|
},
|
||||||
900,
|
800,
|
||||||
1000
|
1280
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
[compare.sh](./compare.sh) is a useful script for viewing a character-by-character diff between the minified outputs of minify-html and html-minifier for a specific test. Pass the test's file name as the first argument.
|
|
@ -0,0 +1 @@
|
||||||
|
Profiling minify-html can be done on Linux by using [profile.sh](./profile.sh), which uses `perf`. The generated report can be used using `perf report`.
|
|
@ -8,7 +8,7 @@ An HTML minifier that provides the functionality of [minify-html](https://github
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
<img alt="Chart showing speed of HTML minifiers" src="https://wilsonl.in/minify-html/bench/0.6.1/core/average-speeds.png">
|
<img width="600" alt="Chart showing speed of HTML minifiers" src="https://wilsonl.in/minify-html/bench/0.6.1/core/average-speeds.png">
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue