aboutsummaryrefslogtreecommitdiff
path: root/bench/snippets
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-06-07 22:32:46 -0700
committerGravatar GitHub <noreply@github.com> 2022-06-07 22:32:46 -0700
commit43de33afc7fcc4cab25f578566e225ba9e4d4258 (patch)
tree141676095981741c3a5740093fee79ed12d4edcd /bench/snippets
parent958fc3d4f5ba2a1fb5b5e1e2b9fe3a4500dbefc6 (diff)
downloadbun-43de33afc7fcc4cab25f578566e225ba9e4d4258.tar.gz
bun-43de33afc7fcc4cab25f578566e225ba9e4d4258.tar.zst
bun-43de33afc7fcc4cab25f578566e225ba9e4d4258.zip
Web Streams API (#176)
* [bun.js] `WritableStream`, `ReadableStream`, `TransformStream`, `WritableStreamDefaultController`, `ReadableStreamDefaultController` & more * Implement `Blob.stream()` * Update streams.test.js * Fix sourcemaps crash * [TextEncoder] 3x faster in hot loops * reading almost works * start to implement native streams * Implement `Blob.stream()` * Implement `Bun.file(pathOrFd).stream()` * Add an extra function * [fs.readFile] Improve performance * make jsc bindings a little easier to work with * fix segfault * faster async/await + readablestream optimizations * WebKit updates * More WebKit updates * Add releaseWEakrefs binding * `bun:jsc` * More streams * Update streams.test.js * Update Makefile * Update mimalloc * Update WebKit * Create bun-jsc.test.js * Faster ReadableStream * Fix off by one & exceptions * Handle empty files/blobs * Update streams.test.js * Move streams to it's own file * temp * impl #1 * take two * good enough for now * Implement `readableStreamToArray`, `readableStreamToArrayBuffer`, `concatArrayBuffers` * jsxOptimizationInlining * Fix crash * Add `jsxOptimizationInline` to Bun.Transpiler * Update Transpiler types * Update js_ast.zig * Automatically choose production mode when NODE_ENV="production" * Update cli.zig * [jsx] Handle defaultProps when inlining * Update transpiler.test.js * uncomment some tests Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'bench/snippets')
-rw-r--r--bench/snippets/concat.js66
-rw-r--r--bench/snippets/escapeHTML.js122
-rw-r--r--bench/snippets/noop.js17
3 files changed, 205 insertions, 0 deletions
diff --git a/bench/snippets/concat.js b/bench/snippets/concat.js
new file mode 100644
index 000000000..46c6e0f7d
--- /dev/null
+++ b/bench/snippets/concat.js
@@ -0,0 +1,66 @@
+import { bench, group, run } from "mitata";
+import { readFileSync } from "fs";
+import { allocUnsafe } from "bun";
+
+function polyfill(chunks) {
+ var size = 0;
+ for (const chunk of chunks) {
+ size += chunk.byteLength;
+ }
+ var buffer = new ArrayBuffer(size);
+ var view = new Uint8Array(buffer);
+ var offset = 0;
+ for (const chunk of chunks) {
+ view.set(chunk, offset);
+ offset += chunk.byteLength;
+ }
+ return buffer;
+}
+
+function polyfillUninitialized(chunks) {
+ var size = 0;
+ for (const chunk of chunks) {
+ size += chunk.byteLength;
+ }
+ var view = allocUnsafe(size);
+
+ var offset = 0;
+ for (const chunk of chunks) {
+ view.set(chunk, offset);
+ offset += chunk.byteLength;
+ }
+ return view.buffer;
+}
+
+const chunkGroups = [
+ [Uint8Array.from([123]), Uint8Array.from([456]), Uint8Array.from([789])],
+ Array.from(readFileSync(import.meta.path)).map((a) => Uint8Array.from([a])),
+ [readFileSync(import.meta.path)],
+ Array.from({ length: 42 }, () => readFileSync(import.meta.path)),
+ Array.from({ length: 2 }, () =>
+ new TextEncoder().encode(readFileSync(import.meta.path, "utf8").repeat(100))
+ ),
+];
+
+for (const chunks of chunkGroups) {
+ group(
+ `${chunks.reduce(
+ (prev, curr, i, a) => prev + curr.byteLength,
+ 0
+ )} bytes for ${chunks.length} chunks`,
+ () => {
+ bench("Bun.concatArrayBuffers", () => {
+ Bun.concatArrayBuffers(chunks);
+ });
+ bench("Uint8Array.set", () => {
+ polyfill(chunks);
+ });
+
+ bench("Uint8Array.set (uninitialized memory)", () => {
+ polyfillUninitialized(chunks);
+ });
+ }
+ );
+}
+
+await run();
diff --git a/bench/snippets/escapeHTML.js b/bench/snippets/escapeHTML.js
new file mode 100644
index 000000000..f186b1d2f
--- /dev/null
+++ b/bench/snippets/escapeHTML.js
@@ -0,0 +1,122 @@
+import { group } from "mitata";
+import { bench, run } from "mitata";
+import { encode as htmlEntityEncode } from "html-entities";
+import { escape as heEscape } from "he";
+
+var bunEscapeHTML = globalThis.escapeHTML || Bun.escapeHTML;
+
+const FIXTURE = require("fs")
+ .readFileSync(import.meta.dir + "/_fixture.txt", "utf8")
+ .split("")
+ .map((a) => {
+ if (a.charCodeAt(0) > 127) {
+ return "a";
+ }
+ return a;
+ })
+ .join("");
+
+const FIXTURE_WITH_UNICODE = require("fs").readFileSync(
+ import.meta.dir + "/_fixture.txt",
+ "utf8"
+);
+
+// from react-dom:
+const matchHtmlRegExp = /["'&<>]/;
+
+function reactEscapeHtml(string) {
+ const str = "" + string;
+ const match = matchHtmlRegExp.exec(str);
+
+ if (!match) {
+ return str;
+ }
+
+ let escape;
+ let html = "";
+ let index;
+ let lastIndex = 0;
+
+ for (index = match.index; index < str.length; index++) {
+ switch (str.charCodeAt(index)) {
+ case 34: // "
+ escape = "&quot;";
+ break;
+ case 38: // &
+ escape = "&amp;";
+ break;
+ case 39: // '
+ escape = "&#x27;"; // modified from escape-html; used to be '&#39'
+ break;
+ case 60: // <
+ escape = "&lt;";
+ break;
+ case 62: // >
+ escape = "&gt;";
+ break;
+ default:
+ continue;
+ }
+
+ if (lastIndex !== index) {
+ html += str.substring(lastIndex, index);
+ }
+
+ lastIndex = index + 1;
+ html += escape;
+ }
+
+ return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
+}
+
+// for (let input of [
+// "<script>alert('xss')</script>",
+// `long string, nothing to escape... `.repeat(9999),
+// `long utf16 string, no esc 🤔🤔🤔🤔🤔` + "tex".repeat(4000),
+// `smol`,
+// // `medium string with <script>alert('xss')</script>`,
+
+// FIXTURE,
+// // "[unicode]" + FIXTURE_WITH_UNICODE,
+// ]) {
+// group(
+// {
+// summary: true,
+// name:
+// `"` +
+// input.substring(0, Math.min(input.length, 32)) +
+// `"` +
+// ` (${input.length} chars)`,
+// },
+// () => {
+// bench(`ReactDOM.escapeHTML`, () => reactEscapeHtml(input));
+// bench(`html-entities.encode`, () => htmlEntityEncode(input));
+// bench(`he.escape`, () => heEscape(input));
+// bench(`Bun.escapeHTML`, () => bunEscapeHTML(input));
+// }
+// );
+// }
+
+for (let input of [
+ `long string, nothing to escape... `.repeat(9999999 * 3),
+ FIXTURE.repeat(8000),
+ // "[unicode]" + FIXTURE_WITH_UNICODE,
+]) {
+ group(
+ {
+ summary: true,
+ name:
+ `"` +
+ input.substring(0, Math.min(input.length, 32)) +
+ `"` +
+ ` (${new Intl.NumberFormat().format(input.length / 100_000_000_0)} GB)`,
+ },
+ () => {
+ // bench(`ReactDOM.escapeHTML`, () => reactEscapeHtml(input));
+ // bench(`html-entities.encode`, () => htmlEntityEncode(input));
+ // bench(`he.escape`, () => heEscape(input));
+ bench(`Bun.escapeHTML`, () => bunEscapeHTML(input));
+ }
+ );
+}
+await run();
diff --git a/bench/snippets/noop.js b/bench/snippets/noop.js
new file mode 100644
index 000000000..789e6abbb
--- /dev/null
+++ b/bench/snippets/noop.js
@@ -0,0 +1,17 @@
+import { bench, run } from "mitata";
+
+var noop = globalThis[Symbol.for("Bun.lazy")]("noop");
+
+bench("function", function () {
+ noop.function();
+});
+
+bench("setter", function () {
+ noop.getterSetter = 1;
+});
+
+bench("getter", function () {
+ noop.getterSetter;
+});
+
+run();