8000 Improve performance with inline typecheck for string parsing by mattyhempstead · Pull Request #4058 · colinhacks/zod · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Improve performance with inline typecheck for string parsing #4058

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mattyhempstead
Copy link
@mattyhempstead mattyhempstead commented Mar 28, 2025

This small change improves the benchmarked speed of string parsing by up to ~70% and realworld by ~20%.

Benchmark

These were run on my Macbook Pro M3.

Before the change:

realworld: valid x 8,305 ops/sec ±1.33% (97 runs sampled)

z.string: empty string x 13,717,506 ops/sec ±0.52% (95 runs sampled)
z.string: short string x 13,772,114 ops/sec ±0.97% (96 runs sampled)
z.string: long string x 13,713,146 ops/sec ±1.06% (97 runs sampled)
z.string: optional string x 10,406,774 ops/sec ±0.44% (95 runs sampled)
z.string: nullable string x 8,216,808 ops/sec ±0.73% (95 runs sampled)
z.string: nullable (null) string x 12,463,414 ops/sec ±0.50% (97 runs sampled)
z.string: invalid: null x 181,548 ops/sec ±1.22% (93 runs sampled)
z.string: manual parser: long x 224,317,422 ops/sec ±6.58% (79 runs sampled)

After the change:

realworld: valid x 9,900 ops/sec ±1.89% (96 runs sampled)

z.string: empty string x 23,594,188 ops/sec ±1.29% (94 runs sampled)
z.string: short string x 24,173,253 ops/sec ±0.82% (98 runs sampled)
z.string: long string x 24,042,133 ops/sec ±1.05% (95 runs sampled)
z.string: optional string x 13,433,944 ops/sec ±1.04% (95 runs sampled)
z.string: nullable string x 9,788,757 ops/sec ±1.66% (95 runs sampled)
z.string: nullable (null) string x 12,800,957 ops/sec ±2.00% (91 runs sampled)
z.string: invalid: null x 178,741 ops/sec ±1.65% (93 runs sampled)
z.string: manual parser: long x 229,858,255 ops/sec ±4.72% (80 runs sampled)

Explanation

In the parse function for ZodString, we are calling getParsedType (utils.ts) through a layer of indirection (this._getType -> getParsedType) in order to determine whether the data type is not a string. Since we don't actually need the full range of responses from getParsedType, we can simplify the logic by performing this negative typecheck inline.

The same is true for most other parse methods (we perform a != type check which can be moved inline), although making this change for strings is the simplest and probably the largest impact.

Summary by CodeRabbit

  • Refactor
    • Streamlined string input validation by replacing an indirect evaluation step with a direct type check. This update reduces unnecessary processing, resulting in improved performance while maintaining consistent error handling for invalid inputs.

Copy link
Contributor
coderabbitai bot commented Mar 28, 2025

Walkthrough

The changes update the validation logic in the ZodString class across both deno/lib/types.ts and src/types.ts. The previous method call to _getType(input) has been removed in favor of a direct inline type check using typeof input.data !== "string". In cases where the input is not a string, a context is generated and an issue is recorded, maintaining the existing issue reporting mechanism. There are no alterations to exported or public entities.

Changes

File(s) Change Summary
deno/lib/types.ts, src/types.ts Replaced the _getType(input) call with a direct inline check using typeof input.data !== "string", removing the intermediate variable and simplifying control flow while retaining issue reporting for type mismatches.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Caller
    participant ZodString as ZodString
    participant Context as ParsingContext

    Caller->>ZodString: _parse(input)
    alt input.data is string
        ZodString->>ZodString: Validate string properties
        ZodString-->>Caller: Return parsed string
    else input.data is not string
        ZodString->>Context: _getOrReturnCtx(input)
        Context-->>ZodString: Return error context with type details
        ZodString->>Context: Record type mismatch issue
        ZodString-->>Caller: Return error context
    end
Loading

Poem

I'm a rabbit with a joyful leap,
Hopping through changes wide and deep.
The code now dances with a simpler check,
No extra hops to trip on tech.
Easter cheers and code so sleek! 🥕✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19c6d2e and cc553fe.

📒 Files selected for processing (2)
  • deno/lib/types.ts (1 hunks)
  • src/types.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
src/types.ts (1)
deno/lib/types.ts (1)
  • input (52-52)
deno/lib/types.ts (1)
src/types.ts (1)
  • input (52-52)
🔇 Additional comments (2)
src/types.ts (1)

779-780: Excellent optimization using inline type checking.

The direct type check typeof input.data !== "string" eliminates the function call overhead of _getType(input), resulting in the significant performance improvements mentioned in the PR objectives (70% in benchmarks, 20% in real-world scenarios).

deno/lib/types.ts (1)

779-780: Excellent performance optimization!

This change replaces a function call to _getType(input) with a direct inline type check. By eliminating the function call overhead, you achieve the ~70% performance improvement mentioned in the PR. Since string parsing is one of the most common operations in Zod, this is a high-value optimization with minimal risk.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
netlify bot commented Mar 28, 2025

Deploy Preview for guileless-rolypoly-866f8a ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit cc553fe
🔍 Latest deploy log https://app.netlify.com/sites/guileless-rolypoly-866f8a/deploys/67e72e5a2265b600080d6d4b
😎 Deploy Preview https://deploy-preview-4058--guileless-rolypoly-866f8a.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
vercel bot commented Mar 28, 2025

Deployment failed with the following error:

Creating the Deployment Timed Out.

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.

1 participant
0