-
Notifications
You must be signed in to change notification settings - Fork 2
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
💡 [major] Prefer MSGPack over JSON #93
base: master
Are you sure you want to change the base?
Conversation
src/lib/RedisCache.ts
Outdated
|
||
import { CachableValue, CacheInstance } from './CacheInstance'; | ||
|
||
const MPACK = new Packr({ moreTypes: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By enabling moreTypes
, we get "free" support for Set
and Map
.
src/lib/RedisCache.ts
Outdated
@@ -212,6 +206,10 @@ export class RedisCache extends CacheInstance { | |||
return false; | |||
} | |||
|
|||
if (value instanceof Buffer) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this check will work. This function is passed the returned value from a redisClient.get() which will be a string
. Incidently, the typing of the function parameter is wrong here 😱 . It should be
public static deserializeValue(value: string | null)
or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Urgh! Right, I tested it with redis directly, but Node's redis lib seems to transform everything into strings. Alright, let me use the string prefix trick, and then I'll rerun the benchmark, to ensure we don't take too much of a performance hit.
0f52aab
to
81f0b37
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 👍, just a couple nits & questions
- Before merge (now), aside local cachette unit tests: did you already run one of our services with this (using
npm link
), and confirm (withredis-cli
) that everything behaves well and looks good? - (If feels valuable after point 2. above) After merge, please test in a staging service with manual
redis-cli
inspection that everything behaves as expected
@@ -72,6 +72,7 @@ | |||
}, | |||
"dependencies": { | |||
"ioredis": "5.x", | |||
"msgpackr": "1.x", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@christianblais looks sane and no-dependencies. However, usual introducing-new-depencency questions: how did you pick it? Were there alternatives, and if yes, what led you to think it's the best one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MessagePack is a well defined standard, so the question was — "which implementation should I pick?". There aren't a ton of options to pick from, and this one stands out as the clear winner in terms of love (number/frequency of commits), popularity, and speed.
Now, I'm aware a lib might be feature-complete with no bugs, hence the lack of activity. But looking at the downloads per week, once more, msgpackr
stood out as the clear winner. That was the end of my investigation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yip that's what I meant. Okay with your annotated screenshot!
@@ -212,6 +206,10 @@ export class RedisCache extends CacheInstance { | |||
return false; | |||
} | |||
|
|||
if (value.startsWith(RedisCache.MSGP_PREFIX)) { | |||
return MPACK.unpack(Buffer.from(value.substring(RedisCache.MSGP_PREFIX.length), 'binary')); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Can you also fix the type of the function param on line 190?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it isn't related to this changeset per se, I did it in another PR.
51cd22e
to
bd4ea75
Compare
Locally tested with two of our main services with no apparent issue. So what do you folk say... ship it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
w00t
Co-authored-by: Ronan Jouchet <[email protected]>
Co-authored-by: Ronan Jouchet <[email protected]>
bd4ea75
to
8a5b5ec
Compare
Cachette cached values aren't meant to be human readable. This lib is meant to be fast. Therefore, I believe we can achieve a little bit more speed by avoiding JSON serialization, and instead use more performant algorithms, such as msgpack. With this PR, I'm replacing JSON with msgpacker. We would incur a small hit on writes, but gain interesting wins on reads.
5000 writes;
5000 reads;
Given cachette is all about optimizing reads, I believe this to be a good trade-off. Here, assuming a 5:1 read:write ratio, we see a 34% overall gain.
1000 reads, 5000 writes
Note: Careful, as this PR is not revertable. Values set as buffer depends on the code present in this PR to be deserialized.