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

Find Performance Bottleneck #68

Open
2 tasks
Skn0tt opened this issue Oct 1, 2020 · 5 comments
Open
2 tasks

Find Performance Bottleneck #68

Skn0tt opened this issue Oct 1, 2020 · 5 comments

Comments

@Skn0tt
Copy link
Collaborator

Skn0tt commented Oct 1, 2020

SuperJSON is somewhat slow - at least compared to not using SuperJSON. Our code currently is written for readability first, and not so much for optimal performance.

  • Analyse the Code for it's bottlenecks
  • Remove them
@tomhooijenga
Copy link
Contributor

This project might be suffering from "death by a thousand cuts", aka there are a whole bunch of statements that in itself might not be very costly but it adds up.
Some quick examples

  • array functions vs a plain old for loop
  • lodash vs native (not always though!)
  • isUndefined() vs ===

@KATT
Copy link
Contributor

KATT commented May 30, 2021

We've addressed this in tRPC by allowing different data transformers for upstream and downstream; upstream (client to server) are usually small payloads parsed by the server that needs to be secure and downstream are usually bigger payloads parsed by the client.

@Skn0tt
Copy link
Collaborator Author

Skn0tt commented May 30, 2021

That's a good idea! Still, I'm pretty sure there should be a way of speeding up SuperJSON to better compete with devalue. But I haven't found it yet 🤷‍♂️

@KATT
Copy link
Contributor

KATT commented May 31, 2021

Some ideas, algos isn't really my speciality, so these are mostly novice common sense

  • You might not need to deep clone the object first (or have an option where this is skipped)
  • Every setDeep()-seem to be traversing through the object
    • Potentially a faster strategy:
      • traverse through the whole object once and have a reference to path to update
      • use the reference to know "dead ends" and break; when there's nothing further down to update
  • Make "slow" features optional
  • Rather than traversing yourself when encoding/serializing, you could try using JSON.stringify replacer & JSON.parse reviver.

For inspiration, you can look at https://github.com/yahoo/serialize-javascript where they have the isJSON-option that makes it "to be over 3x faster".

@RobinTail
Copy link

isSymbol() —> getType()

superjson/src/is.ts

Lines 43 to 44 in 0130a80

export const isSymbol = (payload: any): payload is symbol =>
getType(payload) === 'Symbol';

superjson/src/is.ts

Lines 1 to 2 in 0130a80

const getType = (payload: any): string =>
Object.prototype.toString.call(payload).slice(8, -1);

Performance

Comparison to typeof subject === "symbol"

   ✓ symbol check (2) 9790ms
     name                              hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · regular typeof         15,345,908.19  0.0001  0.0692  0.0001  0.0001  0.0001  0.0001  0.0001  ±0.19%  7672955   fastest
   · superjson::isSymbol()  13,116,368.09  0.0001  0.9246  0.0001  0.0001  0.0001  0.0001  0.0002  ±0.42%  6558185

 BENCH  Summary

  regular typeof - tests/bench/experiment.bench.ts > symbol check
    1.17x faster than superjson::isSymbol()

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

No branches or pull requests

4 participants