Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

perf(ext/web): use base64-simd for atob/btoa #14992

Merged
merged 1 commit into from
Jun 29, 2022

Conversation

Nugine
Copy link
Contributor

@Nugine Nugine commented Jun 28, 2022

resolves #14980

Related: #13841

@CLAassistant
Copy link

CLAassistant commented Jun 28, 2022

CLA assistant check
All committers have signed the CLA.

@cjihrig
Copy link
Contributor

cjihrig commented Jun 28, 2022

@Nugine it looks like there are relevant failures in the CI.

@Nugine
Copy link
Contributor Author

Nugine commented Jun 29, 2022

The decoding function is forgiving-base64-decode. I have fixed it locally.

The step "Remove all ASCII whitespace from data." is even slower than base64 decoding. I'm trying to make it faster. (Nugine/simd#4)

@Nugine
Copy link
Contributor Author

Nugine commented Jun 29, 2022

Bench result:

node v18.4.0
b64Long:     	n = 100,          	dt = 8.134s, 	freq = 12.294/s, 	time = 81.343ms/op
b64Short:     	n = 1000000,          	dt = 0.876s, 	freq = 1142028.234/s, 	time = 876ns/op
deno 1.23.1
b64Long:     	n = 100,          	dt = 0.402s, 	freq = 248.756/s, 	time = 4.020ms/op
b64Short:     	n = 1000000,          	dt = 0.460s, 	freq = 2173913.043/s, 	time = 460ns/op
deno (base64-simd v0.6.2)
b64Long:     	n = 100,          	dt = 0.156s, 	freq = 641.026/s, 	time = 1.560ms/op
b64Short:     	n = 1000000,          	dt = 0.398s, 	freq = 2512562.814/s, 	time = 398ns/op

CPU: Intel(R) Core(TM) i5-9300H CPU @ 2.40GHz

bench function
// Extracted from <https://github.com/denoland/deno/blob/main/cli/bench/deno_common.js>

function bench(name, n, f) {
    const t1 = performance.now();
    for (let i = 0; i < n; ++i) {
        f(i);
    }
    const t2 = performance.now();

    const dt = (t2 - t1) / 1e3;
    const freq = n / dt;
    const time = (t2 - t1) / n;

    const msg = [
        `${name}:     \t`,
        `n = ${n},          \t`,
        `dt = ${dt.toFixed(3)}s, \t`,
        `freq = ${freq.toFixed(3)}/s, \t`,
    ]

    if (time >= 1) {
        msg.push(`time = ${time.toFixed(3)}ms/op`)
    } else {
        msg.push(`time = ${(time * 1e6).toFixed(0)}ns/op`)
    }

    console.log(msg.join(""))
}

function b64Long() {
    const input = "helloworld".repeat(1e5);
    bench("b64Long", 100, () => {
        atob(btoa(input));
    });
}

function b64Short() {
    const input = "123";
    bench("b64Short", 1e6, () => {
        atob(btoa(input));
    });
}

b64Long();
b64Short();

Copy link
Member

@littledivy littledivy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Nugine
Copy link
Contributor Author

Nugine commented Jun 29, 2022

rebased

@Nugine
Copy link
Contributor Author

Nugine commented Jun 29, 2022

baseline (direct rust call)

simd-benches quick mode
base64-simd forgiving_decode_inplace
n = 100      long  = 0.227898ms
n = 1000000  short = 30ns

bun is faster than deno when decoding short strings. I think the main overhead is passing data between js and rust.

node v18.4.0
b64Long:        n = 100,                dt = 8.174s,    freq = 12.234/s,        time = 81.739ms/op
b64Short:       n = 1000000,            dt = 0.912s,    freq = 1096962.697/s,   time = 912ns/op

deno 1.23.1
b64Long:        n = 100,                dt = 0.404s,    freq = 247.525/s,       time = 4.040ms/op
b64Short:       n = 1000000,            dt = 0.476s,    freq = 2100840.336/s,   time = 476ns/op

deno (base64-simd v0.6.2)
b64Long:        n = 100,                dt = 0.158s,    freq = 632.911/s,       time = 1.580ms/op
b64Short:       n = 1000000,            dt = 0.376s,    freq = 2659574.468/s,   time = 376ns/op

bun 0.0.83
b64Long:        n = 100,                dt = 0.440s,    freq = 227.331/s,       time = 4.399ms/op
b64Short:       n = 1000000,            dt = 0.136s,    freq = 7334740.503/s,   time = 136ns/op

@littledivy littledivy merged commit 1328a56 into denoland:main Jun 29, 2022
dsherret pushed a commit to dsherret/deno that referenced this pull request Jun 30, 2022
@Nugine Nugine deleted the pr-base64-simd branch December 10, 2022 05:21
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Optimize atob/btoa by using base64-simd
4 participants