Do not handle extremely rare escaped states in <script>; simplify graph to show single average

This commit is contained in:
Wilson Lin 2020-01-12 17:39:23 +11:00
parent 52592997fb
commit 20c59769fe
8 changed files with 120 additions and 153 deletions

View File

@ -369,4 +369,4 @@ Special handling of some attributes require case sensitive names and values. For
`script` and `style` tags must be closed with `</script>` and `</style>` respectively (case sensitive).
[hyperbuild can handle escaped and double-escaped script content.](./notes/Script%20data.md)
hyperbuild does not handle [escaped and double-escaped](./notes/Script%20data.md) script content.

View File

@ -5,41 +5,44 @@ const tests = require('./tests');
const colours = {
'hyperbuild': '#041f60',
'hyperbuild-nodejs': '#0476d0',
'minimize': '#3cacae',
'html-minifier': '#5d6c89',
'hyperbuild-nodejs': '#1f77b4',
'minimize': '#ff7f0e',
'html-minifier': '#2ca02c',
};
const programNames = ['minimize', 'html-minifier', 'hyperbuild-nodejs'];
const chartOptions = (title, displayLegend, yTick = t => t) => ({
options: {
title: {
display: true,
text: title,
fontColor: '#333',
},
scales: {
xAxes: [{
barPercentage: 0.75,
barPercentage: 0.5,
gridLines: {
color: '#ccc',
color: '#e2e2e2',
},
ticks: {
fontColor: '#222',
fontColor: '#666',
},
}],
yAxes: [{
gridLines: {
color: '#666',
color: '#ccc',
},
ticks: {
callback: yTick,
fontColor: '#222',
fontColor: '#666',
},
}],
},
legend: {
display: displayLegend,
labels: {
fontFamily: 'Ubuntu, sans-serif',
fontFamily: 'Arial, sans-serif',
fontColor: '#000',
},
},
@ -56,31 +59,50 @@ const renderChart = async (file, cfg) => {
const testNames = tests.map(t => t.name).sort();
const speedResults = JSON.parse(fs.readFileSync(path.join(__dirname, 'speed.json'), 'utf8'));
const speedData = programNames.map(program => [
program,
testNames
// Get OP/s for each test.
.map(test => speedResults[test][program] / speedResults[test]['hyperbuild-nodejs'])
// Sum all test OP/s.
.reduce((sum, c) => sum + c)
// Divide by tests count to get average OP/s.
/ testNames.length,
]).sort((a, b) => a[1] - b[1]);
await renderChart('speed', {
type: 'bar',
data: {
labels: testNames,
datasets: ['hyperbuild', 'hyperbuild-nodejs', 'minimize', 'html-minifier'].map(program => ({
label: program,
backgroundColor: colours[program],
data: testNames.map(test => speedResults[test][program] / speedResults[test]['hyperbuild'] * 100),
})),
labels: speedData.map(([n]) => n),
// Node.js version is close enough to Rust version, so leave out Rust results.
// Include it this if this situation changes.
datasets: [{
label: 'Average relative OP/s',
backgroundColor: '#0366d6',
data: speedData.map(([_, v]) => v),
}],
},
...chartOptions('Relative operations per second (higher is better)', true, tick => `${tick}%`),
...chartOptions('Average operations per second (higher is better)', false, tick => `${tick * 100}%`),
});
const sizes = JSON.parse(fs.readFileSync(path.join(__dirname, 'minification.json'), 'utf8'));
const sizeData = programNames.map(program => [
program,
testNames
.map(test => sizes[test][program].relative)
.reduce((sum, c) => sum + c)
/ testNames.length,
]).sort((a, b) => b[1] - a[1]);
await renderChart('minification', {
type: 'bar',
scaleFontColor: 'red',
data: {
labels: testNames,
datasets: ['hyperbuild-nodejs', 'html-minifier', 'minimize'].map(program => ({
label: program,
backgroundColor: colours[program],
data: testNames.map(test => sizes[test][program].relative * 100),
})),
labels: sizeData.map(([n]) => n),
datasets: [{
label: 'Average minified size',
backgroundColor: '#0366d6',
data: sizeData.map(([_, v]) => v),
}],
},
...chartOptions('Relative minified HTML file size (lower is better)', true, tick => `${tick}%`),
...chartOptions('Average minified size (lower is better)', false, tick => `${tick * 100}%`),
});
})();

View File

@ -5,8 +5,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 493123,
"relative": 0.8609366679760814
"absolute": 493190,
"relative": 0.8610536423552005
},
"html-minifier": {
"absolute": 488822,
@ -23,8 +23,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 297108,
"relative": 0.7413114696833979
"absolute": 297113,
"relative": 0.7413239451379411
},
"html-minifier": {
"absolute": 298773,
@ -41,8 +41,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 137131,
"relative": 0.8809592640417317
"absolute": 137191,
"relative": 0.8813447170453742
},
"html-minifier": {
"absolute": 137026,
@ -59,8 +59,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 271470,
"relative": 0.7348248000324821
"absolute": 272622,
"relative": 0.7379430752365098
},
"html-minifier": {
"absolute": 270604,
@ -77,8 +77,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 79853,
"relative": 0.6335729474118506
"absolute": 80085,
"relative": 0.6354136913262878
},
"html-minifier": {
"absolute": 79394,
@ -113,8 +113,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 28860,
"relative": 0.5157900380676639
"absolute": 28918,
"relative": 0.5168266223437528
},
"html-minifier": {
"absolute": 28448,
@ -131,8 +131,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 1888405,
"relative": 0.9523229578616866
"absolute": 1888685,
"relative": 0.9524641619085946
},
"html-minifier": {
"absolute": 1887947,
@ -149,8 +149,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 1116125,
"relative": 0.7234200454355427
"absolute": 1116262,
"relative": 0.7235088424307043
},
"html-minifier": {
"absolute": 1115617,
@ -167,8 +167,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 89741,
"relative": 0.5793517065959108
"absolute": 89844,
"relative": 0.5800166560145643
},
"html-minifier": {
"absolute": 89321,
@ -185,8 +185,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 273277,
"relative": 0.9084916041395864
"absolute": 281124,
"relative": 0.9345784450288063
},
"html-minifier": {
"absolute": 273174,
@ -203,8 +203,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 1351483,
"relative": 0.5539028200832156
"absolute": 1354680,
"relative": 0.5552131046489897
},
"html-minifier": {
"absolute": 1307563,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,74 +1,74 @@
{
"Amazon.html": {
"hyperbuild": 348.52605821546064,
"hyperbuild-nodejs": 165.07093690973286,
"html-minifier": 16.107592839431693,
"minimize": 99.24208700487603
"hyperbuild": 440.8132965717429,
"hyperbuild-nodejs": 421.69855021276993,
"html-minifier": 17.258795822465824,
"minimize": 90.55958994772226
},
"BBC.html": {
"hyperbuild": 498.2348139009136,
"hyperbuild-nodejs": 244.6322429720145,
"html-minifier": 18.585717845341243,
"minimize": 116.27828832819753
"hyperbuild": 492.0329453689757,
"hyperbuild-nodejs": 471.8584948307175,
"html-minifier": 19.7020352249727,
"minimize": 104.87178415350614
},
"Bootstrap.html": {
"hyperbuild": 238.21894278610927,
"hyperbuild-nodejs": 156.53315203999523,
"html-minifier": 8.3990089555115,
"minimize": 22.909077061595145
"hyperbuild": 231.09665327117622,
"hyperbuild-nodejs": 226.67498352524473,
"html-minifier": 8.226880597761307,
"minimize": 20.13372742812355
},
"Bing.html": {
"hyperbuild": 1737.6334081200116,
"hyperbuild-nodejs": 688.4893822559816,
"html-minifier": 78.95988809648134,
"minimize": 437.5366586028663
"hyperbuild": 1778.4702078625266,
"hyperbuild-nodejs": 1658.794145375611,
"html-minifier": 83.98091409603377,
"minimize": 384.94817410652996
},
"Coding Horror.html": {
"hyperbuild": 1197.4089706956722,
"hyperbuild-nodejs": 669.904737573913,
"html-minifier": 45.643674781314395,
"minimize": 173.0258048899911
"hyperbuild": 1168.2795366543119,
"hyperbuild-nodejs": 1078.459574380092,
"html-minifier": 46.48112183626401,
"minimize": 153.319841453279
},
"Google.html": {
"hyperbuild": 1123.9206824500823,
"hyperbuild-nodejs": 920.376725868044,
"html-minifier": 31.321054829311436,
"minimize": 369.0906454521445
"hyperbuild": 1114.801076060868,
"hyperbuild-nodejs": 1019.3514619651979,
"html-minifier": 30.027167989715412,
"minimize": 332.2243603934142
},
"Hacker News.html": {
"hyperbuild": 1839.8486560618867,
"hyperbuild-nodejs": 1255.30693251337,
"html-minifier": 67.45295727773244,
"minimize": 265.7472608824104
"hyperbuild": 1792.733771310799,
"hyperbuild-nodejs": 1733.4960660597985,
"html-minifier": 66.72358457316844,
"minimize": 227.14057132045096
},
"NY Times.html": {
"hyperbuild": 206.64831284965635,
"hyperbuild-nodejs": 54.49167941039783,
"html-minifier": 7.336661842305721,
"minimize": 61.264331562390105
"hyperbuild": 205.6615989494327,
"hyperbuild-nodejs": 184.89340003459205,
"html-minifier": 8.051220803993862,
"minimize": 57.913234028121984
},
"Reddit.html": {
"hyperbuild": 189.6454899629115,
"hyperbuild-nodejs": 84.58158579201455,
"html-minifier": 6.305846537661691,
"minimize": 45.602895635511416
"hyperbuild": 186.794516149638,
"hyperbuild-nodejs": 174.40078706592806,
"html-minifier": 6.803778440125968,
"minimize": 38.92901486989761
},
"Stack Overflow.html": {
"hyperbuild": 795.551445372161,
"hyperbuild-nodejs": 496.1578048486152,
"html-minifier": 39.331066953478285,
"minimize": 154.24858433261213
"hyperbuild": 785.6645799343813,
"hyperbuild-nodejs": 744.9855971158657,
"html-minifier": 40.301363056633434,
"minimize": 136.9552445217857
},
"Twitter.html": {
"hyperbuild": 386.0676346339393,
"hyperbuild-nodejs": 207.95620261405426,
"html-minifier": 42.24757139208541,
"minimize": 129.4921832398901
"hyperbuild": 368.20636689648717,
"hyperbuild-nodejs": 347.59122908382204,
"html-minifier": 42.309450954465014,
"minimize": 135.2904116989639
},
"Wikipedia.html": {
"hyperbuild": 52.81648307515652,
"hyperbuild-nodejs": 32.050455493661815,
"html-minifier": 2.394314136599145,
"minimize": 8.106531334304298
"hyperbuild": 51.59259861536417,
"hyperbuild-nodejs": 51.17247467198595,
"html-minifier": 2.3748941300695545,
"minimize": 7.740053597200842
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,5 +1,6 @@
{
"COMMENT_END": "-->",
"STYLE_END": "</style",
"SCRIPT_END": "</script",
"INSTRUCTION_END": "?>"
}

View File

@ -1,66 +1,10 @@
use crate::err::ProcessingResult;
use crate::proc::Processor;
// See https://www.w3.org/TR/html52/syntax.html#script-data-state and "notes/Script data.md".
enum State {
End,
Normal,
Escaped,
DoubleEscaped,
}
// TODO Optimise all functions in this file.
fn process_script_data_double_escaped(proc: &mut Processor) -> ProcessingResult<State> {
loop {
if chain!(proc.match_seq(b"</script").keep().matched()) {
return Ok(State::Escaped);
};
if chain!(proc.match_seq(b"-->").keep().matched()) {
return Ok(State::Normal);
};
proc.accept()?;
};
}
fn process_script_data_escaped(proc: &mut Processor) -> ProcessingResult<State> {
loop {
if chain!(proc.match_seq(b"<script").keep().matched()) {
return Ok(State::DoubleEscaped);
};
if chain!(proc.match_seq(b"</script").matched()) {
return Ok(State::End);
};
if chain!(proc.match_seq(b"-->").keep().matched()) {
return Ok(State::Normal);
};
proc.accept()?;
};
}
fn process_script_data(proc: &mut Processor) -> ProcessingResult<State> {
loop {
if chain!(proc.match_seq(b"</script").matched()) {
return Ok(State::End);
};
if chain!(proc.match_seq(b"<!--").keep().matched()) {
return Ok(State::Escaped);
};
proc.accept()?;
};
}
include!(concat!(env!("OUT_DIR"), "/gen_pattern_SCRIPT_END.rs"));
pub fn process_script(proc: &mut Processor) -> ProcessingResult<()> {
// NOTE: See "notes/Script data.md".
let mut state = State::Normal;
loop {
state = match state {
State::End => break,
State::Normal => process_script_data(proc)?,
State::Escaped => process_script_data_escaped(proc)?,
State::DoubleEscaped => process_script_data_double_escaped(proc)?,
};
};
// `process_tag` will require closing tag.
chain!(proc.match_while_not_seq(SCRIPT_END).keep());
Ok(())
}