Skip to content

Commit b29a603

Browse files
committed
feat: enable SIMD
1 parent fadca6a commit b29a603

File tree

9 files changed

+1088
-5
lines changed

9 files changed

+1088
-5
lines changed

benchmark/bench-wasm.ts

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { promises as fs } from 'fs'
2+
import { join } from 'path'
3+
4+
import b from 'benny'
5+
6+
const wasm = require(`../wasm`)
7+
const simd = require(`../wasm-simd`)
8+
9+
async function run() {
10+
await wasm.initWasm(fs.readFile(join(__dirname, '../wasm/index_bg.wasm')))
11+
await simd.initWasm(fs.readFile(join(__dirname, '../wasm-simd/index_bg.wasm')))
12+
13+
const svg1 = await fs.readFile(join(__dirname, '../example/text.svg'))
14+
const tiger = await fs.readFile(join(__dirname, '../__test__/tiger.svg'))
15+
const icon = await fs.readFile(join(__dirname, '../__test__/icon-alarm.svg'))
16+
17+
await b.suite(
18+
'resize width',
19+
b.add('resvg-js(Wasm)', () => {
20+
const opts = {
21+
background: '#eeebe6',
22+
fitTo: {
23+
mode: 'width',
24+
value: 1200,
25+
},
26+
logLevel: 'off',
27+
}
28+
const resvg = new wasm.Resvg(svg1, opts)
29+
const pngData = resvg.render()
30+
pngData.asPng()
31+
}),
32+
33+
b.add('resvg-js(Wasm SIMD)', () => {
34+
const opts = {
35+
background: '#eeebe6',
36+
fitTo: {
37+
mode: 'width',
38+
value: 1200,
39+
},
40+
logLevel: 'off',
41+
}
42+
const resvg = new simd.Resvg(svg1, opts)
43+
const pngData = resvg.render()
44+
pngData.asPng()
45+
}),
46+
47+
b.cycle(),
48+
b.complete(),
49+
)
50+
51+
await b.suite(
52+
'resize icon width',
53+
b.add('resvg-js(Wasm)', () => {
54+
const opts = {
55+
fitTo: {
56+
mode: 'width',
57+
value: 386,
58+
},
59+
logLevel: 'off',
60+
}
61+
const resvg = new wasm.Resvg(icon, opts)
62+
const pngData = resvg.render()
63+
pngData.asPng()
64+
}),
65+
66+
b.add('resvg-js(Wasm SIMD)', () => {
67+
const opts = {
68+
fitTo: {
69+
mode: 'width',
70+
value: 386,
71+
},
72+
logLevel: 'off',
73+
}
74+
const resvg = new simd.Resvg(icon, opts)
75+
const pngData = resvg.render()
76+
pngData.asPng()
77+
}),
78+
79+
b.cycle(),
80+
b.complete(),
81+
)
82+
83+
await b.suite(
84+
'default options and no text',
85+
b.add('resvg-js(Wasm)', () => {
86+
const opts = {
87+
logLevel: 'off',
88+
}
89+
const resvg = new wasm.Resvg(tiger, opts)
90+
const pngData = resvg.render()
91+
pngData.asPng()
92+
}),
93+
94+
b.add('resvg-js(Wasm SIMD)', () => {
95+
const opts = {
96+
logLevel: 'off',
97+
}
98+
const resvg = new simd.Resvg(tiger, opts)
99+
const pngData = resvg.render()
100+
pngData.asPng()
101+
}),
102+
103+
b.cycle(),
104+
b.complete(),
105+
)
106+
}
107+
108+
run().catch((e) => {
109+
console.error(e)
110+
})

bundle.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ const commonOptions = {
1212
buildSync({
1313
...commonOptions,
1414
format: 'cjs',
15-
outfile: 'wasm/index.js',
15+
outfile: 'wasm-simd/index.js',
1616
})
1717
buildSync({
1818
...commonOptions,
1919
format: 'esm',
20-
outfile: 'wasm/index.mjs',
20+
outfile: 'wasm-simd/index.mjs',
2121
})
2222
buildSync({
2323
...commonOptions,
2424
format: 'iife',
2525
minify: true,
2626
globalName: 'resvg',
27-
outfile: 'wasm/index.min.js',
27+
outfile: 'wasm-simd/index.min.js',
2828
})

example/wasm-node.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ const fs = require('fs').promises
22
const { join } = require('path')
33
const { performance } = require('perf_hooks')
44

5-
const { Resvg, initWasm } = require('../wasm')
5+
const args = process.argv.slice(2)
6+
const isSimd = args?.length > 0 && args[0] === '--simd'
7+
const wasmDir = isSimd ? 'wasm-simd' : 'wasm'
8+
9+
const { Resvg, initWasm } = require(`../${wasmDir}`)
10+
11+
console.info(isSimd ? '🚀🚀 Enable SIMD' : '🐢🐢 Disable SIMD')
612

713
async function main() {
8-
await initWasm(fs.readFile(join(__dirname, '../wasm/index_bg.wasm')))
14+
await initWasm(fs.readFile(join(__dirname, `../${wasmDir}/index_bg.wasm`)))
915

1016
const svg = await fs.readFile(join(__dirname, './sprite.svg'))
1117
const opts = {

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,19 @@
4949
"scripts": {
5050
"artifacts": "napi artifacts",
5151
"bench": "node -r @swc-node/register benchmark/bench.ts",
52+
"bench:wasm": "node -r @swc-node/register benchmark/bench-wasm.ts",
5253
"bundle": "run-p 'bundle:*'",
5354
"bundle:js": "node bundle.js",
5455
"bundle:dts": "dts-bundle-generator --external-types -o wasm/index.d.ts wasm-binding.ts",
56+
"bundle:dts-simd": "dts-bundle-generator --external-types -o wasm-simd/index.d.ts wasm-binding.ts",
5557
"build": "napi build --platform --release --js js-binding.js --dts js-binding.d.ts",
5658
"build:debug": "napi build --platform --js js-binding.js --dts js-binding.d.ts",
5759
"build:wasm": "run-s build:wasm-web copy-wasm bundle",
60+
"build:wasm-simd": "run-s build:wasm-simd-web copy-wasm-simd bundle",
5861
"build:wasm-web": "wasm-pack build --target web --out-name index --out-dir wasm/dist --release",
62+
"build:wasm-simd-web": "RUSTFLAGS='-C target-feature=+simd128' wasm-pack build --target web --out-name index --out-dir wasm-simd/dist --release --mode no-install",
5963
"copy-wasm": "copyfiles -f wasm/dist/index_bg.wasm ./wasm",
64+
"copy-wasm-simd": "copyfiles -f wasm-simd/dist/index_bg.wasm ./wasm-simd",
6065
"playground": "copyfiles -f playground/index.html ./wasm",
6166
"format": "run-p format:md format:json format:yaml format:source format:rs",
6267
"format:md": "prettier --parser markdown --write './**/*.md'",

wasm-simd/index.d.ts

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Generated by dts-bundle-generator v6.12.0
2+
3+
declare class BBox {
4+
free(): void;
5+
/**
6+
*/
7+
height: number;
8+
/**
9+
*/
10+
width: number;
11+
/**
12+
*/
13+
x: number;
14+
/**
15+
*/
16+
y: number;
17+
}
18+
declare class RenderedImage {
19+
free(): void;
20+
/**
21+
* Write the image data to Uint8Array
22+
* @returns {Uint8Array}
23+
*/
24+
asPng(): Uint8Array;
25+
/**
26+
* Get the PNG height
27+
*/
28+
readonly height: number;
29+
/**
30+
* Get the PNG width
31+
*/
32+
readonly width: number;
33+
}
34+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
35+
export type ResvgRenderOptions = {
36+
font?: {
37+
loadSystemFonts?: boolean;
38+
fontFiles?: string[];
39+
fontDirs?: string[];
40+
defaultFontFamily?: string;
41+
defaultFontSize?: number;
42+
serifFamily?: string;
43+
sansSerifFamily?: string;
44+
cursiveFamily?: string;
45+
fantasyFamily?: string;
46+
monospaceFamily?: string;
47+
};
48+
dpi?: number;
49+
languages?: string[];
50+
shapeRendering?: 0 // optimizeSpeed
51+
| 1 // crispEdges
52+
| 2; // geometricPrecision
53+
textRendering?: 0 // optimizeSpeed
54+
| 1 // optimizeLegibility
55+
| 2; // geometricPrecision'
56+
imageRendering?: 0 // optimizeQuality
57+
| 1; // optimizeSpeed
58+
fitTo?: {
59+
mode: "original";
60+
} | {
61+
mode: "width";
62+
value: number;
63+
} | {
64+
mode: "height";
65+
value: number;
66+
} | {
67+
mode: "zoom";
68+
value: number;
69+
};
70+
background?: string; // Support CSS3 color, e.g. rgba(255, 255, 255, .8)
71+
crop?: {
72+
left: number;
73+
top: number;
74+
right?: number;
75+
bottom?: number;
76+
};
77+
logLevel?: "off" | "error" | "warn" | "info" | "debug" | "trace";
78+
};
79+
/**
80+
* Initialize Wasm module
81+
* @param module_or_path WebAssembly Module or .wasm url
82+
*
83+
*/
84+
export declare const initWasm: (module_or_path: Promise<InitInput> | InitInput) => Promise<void>;
85+
export declare const Resvg: {
86+
new (svg: Uint8Array | string, options?: ResvgRenderOptions): {
87+
free(): void;
88+
render(): RenderedImage;
89+
toString(): string;
90+
innerBBox(): BBox | undefined;
91+
getBBox(): BBox | undefined;
92+
cropByBBox(bbox: BBox): void;
93+
imagesToResolve(): any[];
94+
resolveImage(href: string, buffer: Uint8Array): void;
95+
readonly height: number;
96+
readonly width: number;
97+
};
98+
};
99+
100+
export {};

0 commit comments

Comments
 (0)