mirror of https://github.com/sveltejs/svelte
chore: tidy up benchmark code (#17490)
* add create_test utility * add missing import * DRY * DRY out * mol (this affects benchmark times, because create_test uses 1e3 iterations whereas the old code used 1e4) * move utils.js * WIP * DRY * reduce indirection * more * tidy up * tidy up * colocate * DRY outpull/17497/head
parent
16e9c70d1e
commit
2eb54f57ae
@ -1,91 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
import { busy } from './util.js';
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
let computed1 = $.derived(() => $.get(head));
|
|
||||||
let computed2 = $.derived(() => ($.get(computed1), 0));
|
|
||||||
let computed3 = $.derived(() => (busy(), $.get(computed2) + 1)); // heavy computation
|
|
||||||
let computed4 = $.derived(() => $.get(computed3) + 2);
|
|
||||||
let computed5 = $.derived(() => $.get(computed4) + 3);
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(computed5);
|
|
||||||
busy(); // heavy side effect
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
assert($.get(computed5) === 6);
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
assert($.get(computed5) === 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_avoidable_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_avoidable_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_avoidable_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_avoidable_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
let last = head;
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
for (let i = 0; i < 50; i++) {
|
|
||||||
let current = $.derived(() => {
|
|
||||||
return $.get(head) + i;
|
|
||||||
});
|
|
||||||
let current2 = $.derived(() => {
|
|
||||||
return $.get(current) + 1;
|
|
||||||
});
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(current2);
|
|
||||||
counter++;
|
|
||||||
});
|
|
||||||
last = current2;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
counter = 0;
|
|
||||||
for (let i = 0; i < 50; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
assert($.get(last) === i + 50);
|
|
||||||
}
|
|
||||||
assert(counter === 50 * 50);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_broad_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_broad_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_broad_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_broad_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
let len = 50;
|
|
||||||
const iter = 50;
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
let current = head;
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
let c = current;
|
|
||||||
current = $.derived(() => {
|
|
||||||
return $.get(c) + 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(current);
|
|
||||||
counter++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
counter = 0;
|
|
||||||
for (let i = 0; i < iter; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
assert($.get(current) === len + i);
|
|
||||||
}
|
|
||||||
assert(counter === iter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_deep_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_deep_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_deep_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_deep_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
let width = 5;
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
let current = [];
|
|
||||||
for (let i = 0; i < width; i++) {
|
|
||||||
current.push(
|
|
||||||
$.derived(() => {
|
|
||||||
return $.get(head) + 1;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let sum = $.derived(() => {
|
|
||||||
return current.map((x) => $.get(x)).reduce((a, b) => a + b, 0);
|
|
||||||
});
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(sum);
|
|
||||||
counter++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
assert($.get(sum) === 2 * width);
|
|
||||||
counter = 0;
|
|
||||||
for (let i = 0; i < 500; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
assert($.get(sum) === (i + 1) * width);
|
|
||||||
}
|
|
||||||
assert(counter === 500);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_diamond_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_diamond_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_diamond_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_diamond_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let heads = new Array(100).fill(null).map((_) => $.state(0));
|
|
||||||
const mux = $.derived(() => {
|
|
||||||
return Object.fromEntries(heads.map((h) => $.get(h)).entries());
|
|
||||||
});
|
|
||||||
const splited = heads
|
|
||||||
.map((_, index) => $.derived(() => $.get(mux)[index]))
|
|
||||||
.map((x) => $.derived(() => $.get(x) + 1));
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
splited.forEach((x) => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(x);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(heads[i], i);
|
|
||||||
});
|
|
||||||
assert($.get(splited[i]) === i + 1);
|
|
||||||
}
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(heads[i], i * 2);
|
|
||||||
});
|
|
||||||
assert($.get(splited[i]) === i * 2 + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_mux_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_mux_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_mux_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_mux_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
let size = 30;
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
let current = $.derived(() => {
|
|
||||||
let result = 0;
|
|
||||||
for (let i = 0; i < size; i++) {
|
|
||||||
result += $.get(head);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(current);
|
|
||||||
counter++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
assert($.get(current) === size);
|
|
||||||
counter = 0;
|
|
||||||
for (let i = 0; i < 100; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
assert($.get(current) === i * size);
|
|
||||||
}
|
|
||||||
assert(counter === 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_repeated_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_repeated_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_repeated_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_repeated_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
let width = 10;
|
|
||||||
|
|
||||||
function count(number) {
|
|
||||||
return new Array(number)
|
|
||||||
.fill(0)
|
|
||||||
.map((_, i) => i + 1)
|
|
||||||
.reduce((x, y) => x + y, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
let current = head;
|
|
||||||
let list = [];
|
|
||||||
for (let i = 0; i < width; i++) {
|
|
||||||
let c = current;
|
|
||||||
list.push(current);
|
|
||||||
current = $.derived(() => {
|
|
||||||
return $.get(c) + 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let sum = $.derived(() => {
|
|
||||||
return list.map((x) => $.get(x)).reduce((a, b) => a + b, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(sum);
|
|
||||||
counter++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
const constant = count(width);
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
assert($.get(sum) === constant);
|
|
||||||
counter = 0;
|
|
||||||
for (let i = 0; i < 100; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
assert($.get(sum) === constant - width + i * width);
|
|
||||||
}
|
|
||||||
assert(counter === 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_triangle_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_triangle_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_triangle_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_triangle_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
import { assert, fastest_test } from '../../../utils.js';
|
|
||||||
import * as $ from 'svelte/internal/client';
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
let head = $.state(0);
|
|
||||||
const double = $.derived(() => $.get(head) * 2);
|
|
||||||
const inverse = $.derived(() => -$.get(head));
|
|
||||||
let current = $.derived(() => {
|
|
||||||
let result = 0;
|
|
||||||
for (let i = 0; i < 20; i++) {
|
|
||||||
result += $.get(head) % 2 ? $.get(double) : $.get(inverse);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
let counter = 0;
|
|
||||||
|
|
||||||
const destroy = $.effect_root(() => {
|
|
||||||
$.render_effect(() => {
|
|
||||||
$.get(current);
|
|
||||||
counter++;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy,
|
|
||||||
run() {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, 1);
|
|
||||||
});
|
|
||||||
assert($.get(current) === 40);
|
|
||||||
counter = 0;
|
|
||||||
for (let i = 0; i < 100; i++) {
|
|
||||||
$.flush(() => {
|
|
||||||
$.set(head, i);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
assert(counter === 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_unstable_unowned() {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_unstable_unowned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function kairo_unstable_owned() {
|
|
||||||
let run, destroy;
|
|
||||||
|
|
||||||
const destroy_owned = $.effect_root(() => {
|
|
||||||
// Do 10 loops to warm up JIT
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
const { run, destroy } = setup();
|
|
||||||
run();
|
|
||||||
destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
({ run, destroy } = setup());
|
|
||||||
});
|
|
||||||
|
|
||||||
const { timing } = await fastest_test(10, () => {
|
|
||||||
for (let i = 0; i < 1000; i++) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
destroy();
|
|
||||||
destroy_owned();
|
|
||||||
|
|
||||||
return {
|
|
||||||
benchmark: 'kairo_unstable_owned',
|
|
||||||
time: timing.time.toFixed(2),
|
|
||||||
gc_time: timing.gc_time.toFixed(2)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
export function busy() {
|
|
||||||
let a = 0;
|
|
||||||
for (let i = 0; i < 1_00; i++) {
|
|
||||||
a++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
import { busy } from '../util.js';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
let computed1 = $.derived(() => $.get(head));
|
||||||
|
let computed2 = $.derived(() => ($.get(computed1), 0));
|
||||||
|
let computed3 = $.derived(() => (busy(), $.get(computed2) + 1)); // heavy computation
|
||||||
|
let computed4 = $.derived(() => $.get(computed3) + 2);
|
||||||
|
let computed5 = $.derived(() => $.get(computed4) + 3);
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(computed5);
|
||||||
|
busy(); // heavy side effect
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
assert($.get(computed5) === 6);
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
assert($.get(computed5) === 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
let last = head;
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
|
let current = $.derived(() => {
|
||||||
|
return $.get(head) + i;
|
||||||
|
});
|
||||||
|
let current2 = $.derived(() => {
|
||||||
|
return $.get(current) + 1;
|
||||||
|
});
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(current2);
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
last = current2;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
counter = 0;
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
assert($.get(last) === i + 50);
|
||||||
|
}
|
||||||
|
assert(counter === 50 * 50);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
let len = 50;
|
||||||
|
const iter = 50;
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
let current = head;
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
let c = current;
|
||||||
|
current = $.derived(() => {
|
||||||
|
return $.get(c) + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(current);
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
counter = 0;
|
||||||
|
for (let i = 0; i < iter; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
assert($.get(current) === len + i);
|
||||||
|
}
|
||||||
|
assert(counter === iter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
let width = 5;
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
let current = [];
|
||||||
|
for (let i = 0; i < width; i++) {
|
||||||
|
current.push(
|
||||||
|
$.derived(() => {
|
||||||
|
return $.get(head) + 1;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let sum = $.derived(() => {
|
||||||
|
return current.map((x) => $.get(x)).reduce((a, b) => a + b, 0);
|
||||||
|
});
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(sum);
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
assert($.get(sum) === 2 * width);
|
||||||
|
counter = 0;
|
||||||
|
for (let i = 0; i < 500; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
assert($.get(sum) === (i + 1) * width);
|
||||||
|
}
|
||||||
|
assert(counter === 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let heads = new Array(100).fill(null).map((_) => $.state(0));
|
||||||
|
const mux = $.derived(() => {
|
||||||
|
return Object.fromEntries(heads.map((h) => $.get(h)).entries());
|
||||||
|
});
|
||||||
|
const splited = heads
|
||||||
|
.map((_, index) => $.derived(() => $.get(mux)[index]))
|
||||||
|
.map((x) => $.derived(() => $.get(x) + 1));
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
splited.forEach((x) => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(x);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(heads[i], i);
|
||||||
|
});
|
||||||
|
assert($.get(splited[i]) === i + 1);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(heads[i], i * 2);
|
||||||
|
});
|
||||||
|
assert($.get(splited[i]) === i * 2 + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
let size = 30;
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
let current = $.derived(() => {
|
||||||
|
let result = 0;
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
result += $.get(head);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(current);
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
assert($.get(current) === size);
|
||||||
|
counter = 0;
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
assert($.get(current) === i * size);
|
||||||
|
}
|
||||||
|
assert(counter === 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
let width = 10;
|
||||||
|
|
||||||
|
function count(number) {
|
||||||
|
return new Array(number)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => i + 1)
|
||||||
|
.reduce((x, y) => x + y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
let current = head;
|
||||||
|
let list = [];
|
||||||
|
for (let i = 0; i < width; i++) {
|
||||||
|
let c = current;
|
||||||
|
list.push(current);
|
||||||
|
current = $.derived(() => {
|
||||||
|
return $.get(c) + 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let sum = $.derived(() => {
|
||||||
|
return list.map((x) => $.get(x)).reduce((a, b) => a + b, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(sum);
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
const constant = count(width);
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
assert($.get(sum) === constant);
|
||||||
|
counter = 0;
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
assert($.get(sum) === constant - width + i * width);
|
||||||
|
}
|
||||||
|
assert(counter === 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import { assert } from '../../../utils.js';
|
||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
let head = $.state(0);
|
||||||
|
const double = $.derived(() => $.get(head) * 2);
|
||||||
|
const inverse = $.derived(() => -$.get(head));
|
||||||
|
let current = $.derived(() => {
|
||||||
|
let result = 0;
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
result += $.get(head) % 2 ? $.get(double) : $.get(inverse);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
const destroy = $.effect_root(() => {
|
||||||
|
$.render_effect(() => {
|
||||||
|
$.get(current);
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy,
|
||||||
|
run() {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, 1);
|
||||||
|
});
|
||||||
|
assert($.get(current) === 40);
|
||||||
|
counter = 0;
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
$.flush(() => {
|
||||||
|
$.set(head, i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
assert(counter === 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
import * as $ from 'svelte/internal/client';
|
||||||
|
import { fastest_test } from '../../utils.js';
|
||||||
|
|
||||||
|
export function busy() {
|
||||||
|
let a = 0;
|
||||||
|
for (let i = 0; i < 1_00; i++) {
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} label
|
||||||
|
* @param {() => { run: (i?: number) => void, destroy: () => void }} setup
|
||||||
|
*/
|
||||||
|
export function create_test(label, setup) {
|
||||||
|
return {
|
||||||
|
unowned: async () => {
|
||||||
|
// Do 10 loops to warm up JIT
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
const { run, destroy } = setup();
|
||||||
|
run(0);
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { run, destroy } = setup();
|
||||||
|
|
||||||
|
const { timing } = await fastest_test(10, () => {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
run(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
destroy();
|
||||||
|
|
||||||
|
return {
|
||||||
|
benchmark: `${label}_unowned`,
|
||||||
|
time: timing.time.toFixed(2),
|
||||||
|
gc_time: timing.gc_time.toFixed(2)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
owned: async () => {
|
||||||
|
let run, destroy;
|
||||||
|
|
||||||
|
const destroy_owned = $.effect_root(() => {
|
||||||
|
// Do 10 loops to warm up JIT
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
const { run, destroy } = setup();
|
||||||
|
run(0);
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
({ run, destroy } = setup());
|
||||||
|
});
|
||||||
|
|
||||||
|
const { timing } = await fastest_test(10, () => {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
run(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
destroy();
|
||||||
|
destroy_owned();
|
||||||
|
|
||||||
|
return {
|
||||||
|
benchmark: `${label}_owned`,
|
||||||
|
time: timing.time.toFixed(2),
|
||||||
|
gc_time: timing.gc_time.toFixed(2)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in new issue