Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Deno.KV - Modernized TypeScript randomULID() Generator - Smaller and Optimized #3675

Closed
suchislife801 opened this issue Sep 22, 2023 · 8 comments

Comments

@suchislife801
Copy link

suchislife801 commented Sep 22, 2023

Modernized Javascript randomULID() Generator - Smaller and Optimized

@lino-levan
Copy link
Contributor

ulid has been added to the standard library. If you have a rewrite that is better than that implementation we'd love to take a look!

@lino-levan
Copy link
Contributor

What is the advantage of this implementation over the one in https://deno.land/std/ulid ? I feel like I am misunderstanding. Is it faster? I'd love to get a benchmark there.

@iuioiua
Copy link
Contributor

iuioiua commented Sep 24, 2023

The ULID implementation in the Standard Library is up to 58% faster and easier to understand.

Script:

import { ulid } from "https://deno.land/std@0.202.0/ulid/mod.ts";

Deno.bench("ulid()", { baseline: true }, () => { ulid() });
Deno.bench("randomULID()", () => { randomULID() })

Results (consistent with other runs):

cpu: Apple M2
runtime: deno 1.37.0 (aarch64-apple-darwin)

file:///Users/asher/Desktop/x.ts
benchmark         time (avg)        iter/s             (min … max)       p75       p99      p995
------------------------------------------------------------------ -----------------------------
ulid()           783.36 ns/iter   1,276,552.5 (745.37 ns … 837.99 ns) 786.48 ns 837.99 ns 837.99 ns
randomULID()       1.24 µs/iter     808,566.3     (1.21 µs … 1.28 µs)   1.24 µs   1.28 µs   1.28 µs

summary
  ulid()
   1.58x faster than randomULID()

However, once you remove BigInts, just using numbers, randomULID() becomes 28% faster than the Standard Library implementation. Why are BigInts used instead of numbers?

Results (consistent with other runs and swapping baseline benchmarks):

cpu: Apple M2
runtime: deno 1.37.0 (aarch64-apple-darwin)

file:///Users/asher/Desktop/x.ts
benchmark         time (avg)        iter/s             (min … max)       p75       p99      p995
------------------------------------------------------------------ -----------------------------
ulid()           783.25 ns/iter   1,276,730.8 (755.51 ns … 841.45 ns) 788.45 ns 841.45 ns 841.45 ns
randomULID()     611.92 ns/iter   1,634,208.4  (517.4 ns … 662.48 ns) 625.33 ns 662.48 ns 662.48 ns

summary
  randomULID()
   1.28x faster than ulid()

Really, the Standard Library implementation is still bloody quick. I can't see it being a bottleneck and, therefore, needing further performance optimisation. Either way, it'd be best to submit a PR to https://github.com/denoland/deno_std with these ULID tweaks, and we can go from there. This issue should be moved there too. While related to Deno KV, the ULID implementation lives there 🙂

@kt3k kt3k transferred this issue from denoland/deno Sep 25, 2023
@kt3k
Copy link
Member

kt3k commented Sep 25, 2023

@suchislife801
We significantly reduced the API surface when adopting ULID to deno_std. See #3582

Our version is much simpler than the reference implementation at https://github.com/ulid/javascript

Also we use crypto.getRandomValues() by default, and doesn't allow replacement. Cryptographic concern shouldn't apply to our implementation https://github.com/denoland/deno_std/blob/28840333898d71aaca58c44ef43506dfbde85157/ulid/_util.ts#L34

@lino-levan
Copy link
Contributor

The issue with not using the factory function in the case of us having a factory function is that we need to test the implementation. It's pretty hard to test with stubbing the randomness of the implementation. If you could show a proper way to test your proposed implementation that was simpler I'd love to take a look.

@lino-levan
Copy link
Contributor

Let's try to be respectful here. When I'm talking about testing, I am referring to unit testing. The code you posted, while cool, is definitely closer to "fuzzing" than "testing". Properly testing things like MULID requires more than just fuzzing, unfortunately. That being said, any reasonably correct ULID implementation will essentially never get a collision, so I see the value in testing that. If you would like, you could PR your collision test file into the ulid module.

@lino-levan
Copy link
Contributor

Sure, thanks for opening an issue. I'd love to chat more if you are interested.

@suchislife801
Copy link
Author

I am interested in deleting this entire issue but that is also not possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants