diff --git a/README.md b/README.md index 3779a44..18bb3bf 100644 --- a/README.md +++ b/README.md @@ -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) -Chart showing speed of HTML minifiers -Chart showing compression of HTML minifiers +Chart showing speed of HTML minifiersChart showing compression of HTML minifiers 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. diff --git a/bench/README.md b/bench/README.md index 48fef51..93c6c5d 100644 --- a/bench/README.md +++ b/bench/README.md @@ -6,12 +6,7 @@ It also contains a set of common web pages as tests for benchmarking. ## 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: - -- 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: +Each minifier is run against each file in the [inputs](./inputs) folder, which are HTML pages fetched from popular websites: |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: -Chart showing speed of HTML minifiers per test Chart showing effectiveness of HTML minifiers per test +Chart showing speed of HTML minifiers per testChart showing effectiveness of HTML minifiers per test -Since speed depends on the input, speed charts show performance relative to the Node.js 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. +Results depend on the input, so charts show performance relative to minify-html as a percentage. ## 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 [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 [run](./run) 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. - -## 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`. diff --git a/bench/graph.js b/bench/graph.js index b150649..b8067d7 100644 --- a/bench/graph.js +++ b/bench/graph.js @@ -1,7 +1,7 @@ -const results = require("./results"); +const fs = require("fs/promises"); const https = require("https"); const path = require("path"); -const fs = require("fs/promises"); +const results = require("./results"); const GRAPHS_DIR = path.join(__dirname, "graphs"); 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 speedColours = { - "@minify-html/js": "#2e61bd", "minify-html": "#2e61bd", "minify-html-onepass": "#222", }; @@ -21,12 +20,57 @@ const sizeColours = { }; 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) => ({ options: { legend: { display: true, labels: { fontColor: "#000", + fontSize: 20, }, }, 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) => new Promise((resolve, reject) => { const req = https.request("https://quickchart.io/chart", { @@ -147,9 +145,7 @@ const renderChart = (cfg, width, height) => await fs.mkdir(GRAPHS_DIR, { recursive: true }); const res = results.calculate(); - const speedMinifiers = [...res.minifiers].sort( - (a, b) => res.minifierAvgOps[a] - res.minifierAvgOps[b] - ); + const speedMinifiers = ["html-minifier", "minimize", "minify-html", "minify-html-onepass"]; const sizeMinifiers = ["minimize", "html-minifier", "minify-html"]; const inputs = Object.keys(res.inputSizes).sort(); @@ -159,7 +155,7 @@ const renderChart = (cfg, width, height) => { type: "bar", data: { - labels: speedMinifiers.map((m) => m.replace(" (", "\n(")), + labels: speedMinifiers, datasets: [ { backgroundColor: speedMinifiers.map( @@ -184,7 +180,7 @@ const renderChart = (cfg, width, height) => { type: "bar", data: { - labels: sizeMinifiers.map((m) => m.replace(" (", "\n(")), + labels: sizeMinifiers, datasets: [ { backgroundColor: sizeMinifiers.map( @@ -212,14 +208,14 @@ const renderChart = (cfg, width, height) => label: minifier, data: inputs.map( (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, - 1000 + 800, + 1280 ) ); @@ -232,13 +228,13 @@ const renderChart = (cfg, width, height) => labels: inputs, datasets: sizeMinifiers.map((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, - 1000 + 800, + 1280 ) ); })(); diff --git a/debug/diff/README.md b/debug/diff/README.md new file mode 100644 index 0000000..104cf4a --- /dev/null +++ b/debug/diff/README.md @@ -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. diff --git a/debug/prof/README.md b/debug/prof/README.md new file mode 100644 index 0000000..ba040be --- /dev/null +++ b/debug/prof/README.md @@ -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`. diff --git a/rust/onepass/README.md b/rust/onepass/README.md index 9b35c39..553e601 100644 --- a/rust/onepass/README.md +++ b/rust/onepass/README.md @@ -8,7 +8,7 @@ An HTML minifier that provides the functionality of [minify-html](https://github ## Performance -Chart showing speed of HTML minifiers +Chart showing speed of HTML minifiers ## Usage