← 输入框|github.com|刷新
Skip to content

fix(client): keep String.prototype in fast mode after defining VerbatimString - #3479

Merged
nkaradzhov merged 2 commits into
redis:masterfrom
Ceereals:fix/verbatim-string-fast-prototype
Sep 28, 2026
Merged

nkaradzhov merged 2 commits into
redis:masterfrom
Ceereals:fix/verbatim-string-fast-prototype

Conversation

@Ceereals

@Ceereals Ceereals commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Description

This pull request fixes the slowdown of string code that starts as soon as @redis/client is loaded on V8.

Fixes #3478

class VerbatimString extends String switches String.prototype to dictionary mode, and method calls on primitive strings never switch it back. One named property store on an object that inherits from String.prototype, right after the class, restores fast mode. The VerbatimString API and the decoder do not change.

escape-html repro from the issue, Node v26.10.0 ops/s
no redis 192,843 to 218,106
redis loaded 73,540 to 78,211
redis loaded, with this fix 200,196 to 219,576

The new spec loads the client in a fresh node --allow-natives-syntax process, with require and with import(), and checks %HasFastProperties(String.prototype). It fails without the fix and passes with it on Node 20 and 22.

npm test -w @redis/client passes except Socket reconnectStrategy retry counter is sequential after a post-ready socket loss, which also fails on master on my macOS machine.


Checklist

  • Does npm test pass with this change (including linting)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?

Note

Low Risk
Localized V8 workaround with no API changes; tests guard against polluting string prototypes.

Overview
Fixes a process-wide V8 performance regression when @redis/client loads: defining VerbatimString extends String was putting String.prototype into dictionary (“slow”) mode, which slowed ordinary string operations for the rest of the process.

After the class, the PR adds a one-line side-channel store (Object.create(String.prototype).redisVerbatimString = true) so String.prototype returns to fast mode without changing VerbatimString behavior or RESP decoding.

New tests assert redisVerbatimString is not visible on String.prototype or VerbatimString instances, and spawn fresh Node processes (CJS require and ESM import of the client) to assert %HasFastProperties(String.prototype) stays true after load.

Reviewed by Cursor Bugbot for commit c7c69ae. Bugbot is set up for automated code reviews on this repo. Configure here.

@nkaradzhov nkaradzhov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @Ceereals, great catch! LGTM

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

Successfully merging this pull request may close these issues.

Loading redis slows down string-heavy code in the whole process (about 3x for escape-html) on V8

2 participants