mirror of
https://github.com/penpot/penpot.git
synced 2025-08-06 14:38:27 +02:00
🎉 Add comparison tool to WASM playground
This commit is contained in:
parent
6fc63f14a0
commit
aeee05c90d
2 changed files with 163 additions and 3 deletions
158
frontend/resources/wasm-playground/comparison.html
Normal file
158
frontend/resources/wasm-playground/comparison.html
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>WebAssembly - Comparison</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
init, addShapeSolidFill, assignCanvas, hexToU32ARGB, getRandomInt, getRandomColor,
|
||||||
|
getRandomFloat, useShape, setShapeChildren, setupInteraction
|
||||||
|
} from './js/lib.js';
|
||||||
|
|
||||||
|
const url = new URL(location);
|
||||||
|
const files = url.searchParams.getAll('files');
|
||||||
|
if (!files) {
|
||||||
|
createError('URL param "files" not specified', 'You need to specify a file list using "files" like: ?files=/js/a.js&files=/js/b.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn = url.searchParams.get('fn');
|
||||||
|
if (!fn) {
|
||||||
|
createError('URL param "fn" not specified', 'You need to specify the module function to call');
|
||||||
|
}
|
||||||
|
|
||||||
|
const width = parseInt(url.searchParams.get('width') ?? 320, 10);
|
||||||
|
const height = parseInt(url.searchParams.get('height') ?? 200, 10);
|
||||||
|
const shapes = parseInt(url.searchParams.get('shapes') ?? 10, 10);
|
||||||
|
const iterations = parseInt(url.searchParams.get('iterations') ?? 1_000, 10);
|
||||||
|
|
||||||
|
function prepare(Module, canvas) {
|
||||||
|
init(Module);
|
||||||
|
assignCanvas(canvas);
|
||||||
|
Module._set_canvas_background(hexToU32ARGB("#FABADA", 1));
|
||||||
|
Module._set_view(1, 0, 0);
|
||||||
|
|
||||||
|
const children = [];
|
||||||
|
for (let shape = 0; shape < shapes; shape++) {
|
||||||
|
const uuid = crypto.randomUUID();
|
||||||
|
children.push(uuid);
|
||||||
|
|
||||||
|
useShape(uuid);
|
||||||
|
|
||||||
|
Module._set_parent(0, 0, 0, 0);
|
||||||
|
Module._set_shape_type(3);
|
||||||
|
const x1 = getRandomInt(0, canvas.width);
|
||||||
|
const y1 = getRandomInt(0, canvas.height);
|
||||||
|
const width = getRandomInt(20, 100);
|
||||||
|
const height = getRandomInt(20, 100);
|
||||||
|
Module._set_shape_selrect(x1, y1, x1 + width, y1 + height);
|
||||||
|
|
||||||
|
const color = getRandomColor();
|
||||||
|
const argb = hexToU32ARGB(color, getRandomFloat(0.1, 1.0));
|
||||||
|
addShapeSolidFill(argb)
|
||||||
|
}
|
||||||
|
|
||||||
|
useShape("00000000-0000-0000-0000-000000000000");
|
||||||
|
setShapeChildren(children);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createElement(tag, attribs, children) {
|
||||||
|
const e = document.createElement(tag);
|
||||||
|
if (attribs) {
|
||||||
|
for (const [name, value] of Object.entries(attribs)) {
|
||||||
|
if (name === 'style') {
|
||||||
|
for (const [styleName, styleValue] of Object.entries(value)) {
|
||||||
|
e.style.setPropertyValue(styleName, styleValue);
|
||||||
|
}
|
||||||
|
} else if (name === 'class') {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
e.className = value;
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
e.classList.add(...value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
e.setAttribute(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (children) {
|
||||||
|
if (typeof children === 'string'
|
||||||
|
|| typeof children === 'number'
|
||||||
|
|| typeof children === 'boolean'
|
||||||
|
) {
|
||||||
|
e.textContent = children;
|
||||||
|
} else if (Array.isArray(children)) {
|
||||||
|
e.append(...children);
|
||||||
|
} else {
|
||||||
|
e.append(children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createError(title, description) {
|
||||||
|
document.body.append(
|
||||||
|
createElement('div', { class: ['error'] }, [
|
||||||
|
createElement('h1', { class: ['title'] }, title),
|
||||||
|
createElement('p', { class: ['description'] }, description)
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCanvas(width, height) {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
const durations = new Map()
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
const module = await import(file);
|
||||||
|
// console.log(module.default);
|
||||||
|
const instance = await module.default();
|
||||||
|
const canvas = createCanvas(width, height);
|
||||||
|
prepare(instance, canvas);
|
||||||
|
let totalDuration = 0;
|
||||||
|
for (let iteration = 0; iteration < iterations; iteration++) {
|
||||||
|
const startMark = performance.mark(`${file}:begin`);
|
||||||
|
instance[fn]();
|
||||||
|
const endMark = performance.mark(`${file}:end`);
|
||||||
|
|
||||||
|
const { duration } = performance.measure(file, startMark.name, endMark.name);
|
||||||
|
totalDuration += duration;
|
||||||
|
}
|
||||||
|
totalDuration /= iterations;
|
||||||
|
console.log(file, fn, totalDuration);
|
||||||
|
durations.set(file, totalDuration);
|
||||||
|
|
||||||
|
document.body.append(canvas);
|
||||||
|
} catch (error) {
|
||||||
|
createError('Error', error.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function min([aFile, aDuration], [bFile, bDuration]) {
|
||||||
|
if (aDuration < bDuration) {
|
||||||
|
return [aFile, aDuration];
|
||||||
|
}
|
||||||
|
return [bFile, bDuration];
|
||||||
|
}
|
||||||
|
|
||||||
|
function max([aFile, aDuration], [bFile, bDuration]) {
|
||||||
|
if (aDuration > bDuration) {
|
||||||
|
return [aFile, aDuration];
|
||||||
|
}
|
||||||
|
return [bFile, bDuration];
|
||||||
|
}
|
||||||
|
|
||||||
|
const [minFile, minDuration] = durations.entries().reduce((a, b) => min(a, b), ['', Infinity]);
|
||||||
|
const [maxFile, maxDuration] = durations.entries().reduce((a, b) => max(a, b), ['', -Infinity]);
|
||||||
|
console.log('Min', minFile, minDuration);
|
||||||
|
console.log('Max', maxFile, maxDuration);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
|
_BUILD_NAME="${_BUILD_NAME:-render_wasm}"
|
||||||
|
|
||||||
_SCRIPT_DIR=$(dirname $0);
|
_SCRIPT_DIR=$(dirname $0);
|
||||||
pushd $_SCRIPT_DIR;
|
pushd $_SCRIPT_DIR;
|
||||||
|
|
||||||
|
@ -11,9 +13,9 @@ export SKIA_BINARIES_URL=${SKIA_BINARIES_URL:-"https://github.com/penpot/skia-bi
|
||||||
|
|
||||||
cargo build $_CARGO_PARAMS
|
cargo build $_CARGO_PARAMS
|
||||||
|
|
||||||
cp target/wasm32-unknown-emscripten/$_BUILD_MODE/render_wasm.js ../frontend/resources/public/js/
|
cp target/wasm32-unknown-emscripten/$_BUILD_MODE/render_wasm.js ../frontend/resources/public/js/$_BUILD_NAME.js
|
||||||
cp target/wasm32-unknown-emscripten/$_BUILD_MODE/render_wasm.wasm ../frontend/resources/public/js/
|
cp target/wasm32-unknown-emscripten/$_BUILD_MODE/render_wasm.wasm ../frontend/resources/public/js/$_BUILD_NAME.wasm
|
||||||
|
|
||||||
sed -i "s/render_wasm.wasm/render_wasm.wasm?version=develop/g" ../frontend/resources/public/js/render_wasm.js;
|
sed -i "s/render_wasm.wasm/$_BUILD_NAME.wasm?version=develop/g" ../frontend/resources/public/js/$_BUILD_NAME.js;
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue