Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
52972ff01abab19a5861ac2364efc7471c336ae7
d0530dbba74c87bbeb02433a490c49c28c1deb9d
8546f1fd2784ef579ef951c6d3ec4c20b1b156c5
353fd24b7d01420d405377985dc5a43ea7b69498
2 changes: 2 additions & 0 deletions .gitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[blame]
ignoreRevsFile = .git-blame-ignore-revs
1 change: 1 addition & 0 deletions .husky/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_
8 changes: 8 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# run prettier on staged files
npx lint-staged

# typecheck
make lint
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.min.js
*.min.css
build
src/intro.js
src/outro.js
test/support/jquery-1.5.2.js
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"singleQuote": true
}
14 changes: 11 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ BUILD_DIR_EXISTS = $(BUILD_DIR)/.exists--used_by_Makefile
# -*- Build tasks -*-
#

.PHONY: all basic dev js uglify css font clean
.PHONY: all basic dev js uglify css font clean setup-gitconfig prettify-all
all: font css uglify
basic: $(UGLY_BASIC_JS) $(BASIC_CSS)
unminified_basic: $(BASIC_JS) $(BASIC_CSS)
Expand All @@ -114,6 +114,14 @@ css: $(BUILD_CSS)
font: $(FONT_TARGET)
clean:
rm -rf $(BUILD_DIR)
# This adds an entry to your local .git/config file that looks like this:
# [include]
# path = ../.gitconfig
# that tells git to include the additional configuration specified inside the .gitconfig file that's checked in here.
setup-gitconfig:
@git config --local include.path ../.gitconfig
prettify-all:
npx prettier --write '**/*.{ts,js,css,html}'

$(BUILD_JS): $(INTRO) $(SOURCES_FULL) $(OUTRO) $(BUILD_DIR_EXISTS)
cat $^ | ./script/escape-non-ascii | ./script/tsc-emit-only > $@
Expand Down Expand Up @@ -143,7 +151,7 @@ $(BASIC_CSS): $(CSS_SOURCES) $(NODE_MODULES_INSTALLED) $(BUILD_DIR_EXISTS)

$(NODE_MODULES_INSTALLED): package.json
test -e $(NODE_MODULES_INSTALLED) || rm -rf ./node_modules/ # robust against previous botched npm install
NODE_ENV=development npm install
NODE_ENV=development npm ci
touch $(NODE_MODULES_INSTALLED)

$(BUILD_DIR_EXISTS):
Expand All @@ -169,7 +177,7 @@ test: dev $(BUILD_TEST) $(BASIC_JS) $(BASIC_CSS)
@echo "** now open test/{unit,visual}.html in your browser to run the {unit,visual} tests. **"
benchmark: dev $(BUILD_TEST) $(BASIC_JS) $(BASIC_CSS)
@echo
@echo "** now open benchmark/select.html in your browser. **"
@echo "** now open benchmark/{render,select}.html in your browser. **"

$(BUILD_TEST): $(INTRO) $(SOURCES_FULL) $(UNIT_TESTS) $(OUTRO) $(BUILD_DIR_EXISTS)
cat $^ | ./script/tsc-emit-only > $@
Expand Down
173 changes: 173 additions & 0 deletions benchmark/render.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=624" />

<title>MathQuill Performance Test Page</title>

<link rel="stylesheet" type="text/css" href="../build/mathquill.css" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/3.0.5/seedrandom.min.js"></script>
<script
type="text/javascript"
src="../test/support/jquery-1.5.2.js"
></script>
<script type="text/javascript">
window.onerror = function (err) {
document.querySelector('html').style.background = 'red';
};
</script>
<script type="text/javascript" src="../build/mathquill.js"></script>

<style type="text/css">
body {
font-size: 0.8em;
}
.test-case {
margin-top: 1em;
}
</style>
</head>
<body>
<div id="body">
<h1>MathQuill performance test page</h1>
<p>
This page randomly generates one or more latex expressions and times how
long it takes to mathquillify them. Query parameters:
</p>
<ul>
<li>
maxDepth: max depth of randomly generated latex expressions (default:
6)
</li>
<li>
maxLength: (approximate) max length of randomly generated latex
expressions (default: 2048)
</li>
<li>samples: the number of expressions to generate (default: 1)</li>
<li>
seed: random seed (to generate same expressions across page loads)
</li>
</ul>

<textarea></textarea>
<button id="run-button">Run with custom latex</button>
<div id="results"></div>
<h3>All MQ render times:</h3>
<input id="all-results" type="text" />
</div>

<script type="text/javascript">
const MQ = MathQuill.getInterface(MathQuill.getInterface.MAX);
const params = new URLSearchParams(window.location.search);
if (!params.has('seed')) {
params.append('seed', Math.random().toString(16).slice(2, 10));
window.location.href = window.location.href + '?' + params.toString();
}
const MAX_DEPTH = params.get('maxDepth') || 6;
const MAX_LENGTH = params.get('maxLength') || 2048;
const NUM_SAMPLES = params.has('samples')
? parseInt(params.get('samples'))
: 1;
const random = new Math.seedrandom(params.get('seed'));

window.results = [];
for (let i = 0; i < NUM_SAMPLES; i++) {
const latex = randomLatex();
run(latex);
}
printResults();

document
.querySelector('#run-button')
.addEventListener('click', async () => {
run(document.querySelector('textarea').value);
printResults();
});

function run(latex) {
const div = document.createElement('div');
div.classList.add('test-case');
div.innerHTML = `
<div class="test-case-render">
<div><span class="mathquill-math-field"></span></div>
<div><span class="html-only mq-math-mode"></span></div>
</div>
<div class="mq-result"></div>
<div class="html-result"></div>
`;
document.querySelector('#results').appendChild(div);

const mqElement = div.querySelector('.mathquill-math-field');
const htmlElement = div.querySelector('.html-only');

mqElement.innerText = latex;

let start = performance.now();
MQ.MathField(mqElement);
// Force syncronous layout
document.body.getBoundingClientRect();
const mqDuration = performance.now() - start;

const html = mqElement.innerHTML;
start = performance.now();
htmlElement.innerHTML = html;
// Force syncronous layout
document.body.getBoundingClientRect();
const htmlDuration = performance.now() - start;
results.push({ latex, mqDuration, htmlDuration });

div.querySelector('.mq-result').innerText = `MQ: ${mqDuration.toFixed(
2
)} ms`;
div.querySelector(
'.html-result'
).innerText = `HTML: ${htmlDuration.toFixed(2)} ms`;
}

function printResults() {
document.querySelector('#all-results').value = `[${results
.map((r) => r.mqDuration.toFixed(2))
.join(',')}]`;
}

function randomLatex(depth = MAX_DEPTH) {
if (depth <= 0) {
return randomInteger(randomInteger(1));
}

const randomLatexTemplates = [
[(a, b) => `\\frac{${a}}{${b}}`, 2],
[(a, b) => `${a}+${b}`, 2],
[(a) => `\\sqrt{${a}}`, 1],
[(a, b) => `${a}^{${b}}`, 2],
[(a, b) => `${a}_{${b}}`, 2],
[(...args) => `\\left[${args.join(',')}\\right]`, -1],
[(a) => `\\left(${a}\\right)`, 1],
];

let [fn, arity] =
randomLatexTemplates[
Math.floor(random() * randomLatexTemplates.length)
];
const args = [];
if (arity < 0) {
arity = randomInteger(2);
}
let length = 0;
for (let i = 0; i < arity; i++) {
const arg = randomLatex(depth - 1);
length += arg.length;
if (length + arg.length > MAX_LENGTH) break;
args.push(arg);
}
return fn(...args);
}

function randomInteger(maxDigits) {
return Math.floor(random() * Math.pow(10, maxDigits));
}
</script>
</body>
</html>
130 changes: 66 additions & 64 deletions benchmark/select.html
Original file line number Diff line number Diff line change
@@ -1,77 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=624" />

<meta charset="UTF-8">
<meta name="viewport" content="width=624">
<title>MathQuill Select benchmark</title>

<title>MathQuill Select benchmark</title>
<link rel="stylesheet" type="text/css" href="support/home.css" />
<link rel="stylesheet" type="text/css" href="../build/mathquill.css" />
</head>
<body>
<p>Benchmark inserting and then selecting n characters</p>
<button id="run-button">Run</button>
<div>
<span id="editable" style="width: 10em"></span>
</div>
<table id="report">
<thead>
<tr>
<th>nchars</th>
<th>render (ms)</th>
<th>select (ms)</th>
</tr>
</thead>
</table>
<script
type="text/javascript"
src="../test/support/jquery-1.5.2.js"
></script>
<script type="text/javascript" src="../build/mathquill.js"></script>
<script type="text/javascript">
var MQ = MathQuill.getInterface(MathQuill.getInterface.MAX);

<link rel="stylesheet" type="text/css" href="support/home.css">
<link rel="stylesheet" type="text/css" href="../build/mathquill.css">
var editableElt = document.getElementById('editable');
var mq = MQ.MathField(editableElt);
var reportElt = document.getElementById('report');

</head>
<body>
<p>Benchmark inserting and then selecting n characters</p>
<button id="run-button">Run</button>
<div>
<span id="editable" style="width: 10em;"></span>
</div>
<table id="report">
<thead>
<tr>
<th>nchars</th>
<th>render (ms)</th>
<th>select (ms)</th>
</tr>
</thead>
</table>
<script type="text/javascript" src="../test/support/jquery-1.5.2.js"></script>
<script type="text/javascript" src="../build/mathquill.js"></script>
<script type="text/javascript">
var MQ = MathQuill.getInterface(MathQuill.getInterface.MAX);
function runOne(n) {
var rowElt = document.createElement('tr');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
rowElt.appendChild(td1);
rowElt.appendChild(td2);
rowElt.appendChild(td3);

var editableElt = document.getElementById('editable');
var mq = MQ.MathField(editableElt);
var reportElt = document.getElementById('report');
td1.textContent = n;

function runOne(n) {
var rowElt = document.createElement('tr');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
rowElt.appendChild(td1);
rowElt.appendChild(td2);
rowElt.appendChild(td3);
var mark = performance.now();
mq.latex(Array(n + 1).join('1'));
var insert = performance.now();
td2.textContent = (insert - mark).toFixed(2);
mark = insert;
mq.select();
var select = performance.now();
td3.textContent = (select - mark).toFixed(2);

td1.textContent = n;
reportElt.appendChild(rowElt);
}

var mark = performance.now();
mq.latex(Array(n+1).join('1'));
var insert = performance.now();
td2.textContent = (insert - mark).toFixed(2);
mark = insert;
mq.select();
var select = performance.now();
td3.textContent = (select - mark).toFixed(2);
var i = 0;
var sizes = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000];

reportElt.appendChild(rowElt);
}
function runNext() {
runOne(sizes[i]);
i += 1;
if (i >= sizes.length) return;
setTimeout(runNext, 100);
}


var i = 0;
var sizes = [1,2,5,10,20,50,100,200,500,1000,2000];

function runNext() {
runOne(sizes[i]);
i += 1;
if (i >= sizes.length) return;
setTimeout(runNext, 100);
}

document.getElementById('run-button').addEventListener('click', function () {
runNext();
});
</script>
</body>
document
.getElementById('run-button')
.addEventListener('click', function () {
runNext();
});
</script>
</body>
</html>
Loading