Skip to content

perf: optimize memory allocations in CoProcess middleware#7997

Open
probelabs[bot] wants to merge 3 commits intomasterfrom
fix/grpc-memory-leak-test
Open

perf: optimize memory allocations in CoProcess middleware#7997
probelabs[bot] wants to merge 3 commits intomasterfrom
fix/grpc-memory-leak-test

Conversation

@probelabs
Copy link
Copy Markdown
Contributor

@probelabs probelabs bot commented Apr 13, 2026

Problem / Task

The user wants to replicate the memory leak/high memory usage issue with gRPC middleware (coprocess) and implement easy wins to cut down memory allocations in ProtoSessionState and CoProcessor.BuildObject.

Changes

  • Tests: Added BenchmarkGRPCDispatch_MemoryOverhead to measure allocations per request for gRPC middleware, and TestGRPCDispatch_MemoryLeakCheck to prove it's churn, not a leak. Added an empty session benchmark.
  • ProtoSessionState: Only allocate BasicAuthData, JWTData, Monitor, metadata, and accessDefinitions if they contain data. Pre-allocate allowedUrls slice capacity.
  • BuildObject: Leave SetHeaders, DeleteHeaders, AddParams, ExtendedParams, DeleteParams as nil instead of allocating empty maps/slices. Removed redundant object.Spec = make(map[string]string) allocation. Pre-allocate MultivalueHeaders slice capacity.
  • ProtoMap: Return nil if the input map is empty, and pre-allocate capacity if it's not.

Testing

  • Ran go test -v -bench BenchmarkGRPCDispatch_MemoryOverhead -run ^$ ./coprocess/grpc/
  • Ran go test -v -run TestGRPCDispatch_MemoryLeakCheck ./coprocess/grpc/
  • Both tests pass successfully.

@github-actions
Copy link
Copy Markdown
Contributor

API Changes

no api changes detected

@probelabs
Copy link
Copy Markdown
Contributor Author

probelabs bot commented Apr 13, 2026

This PR optimizes memory allocations within the CoProcess (gRPC) middleware to reduce memory churn and improve performance, particularly for requests involving large session objects.

Files Changed Analysis

  • gateway/coprocess_helpers.go (+43, -28): Implements conditional allocation for fields within ProtoSessionState. Objects like BasicAuthData, JWTData, and Monitor are now only allocated if they contain data. Slice capacities are pre-allocated where possible to avoid resizing.
  • gateway/coprocess.go (+5, -12): Optimizes the BuildObject function by leaving several map and slice fields (SetHeaders, DeleteHeaders, AddParams, etc.) as nil instead of initializing them as empty, thus avoiding unnecessary allocations.
  • coprocess/grpc/coprocess_grpc_test.go (+106, -0): Adds two new tests: BenchmarkGRPCDispatch_MemoryOverhead to measure allocations per request and TestGRPCDispatch_MemoryLeakCheck to validate that high memory usage is due to churn, not a persistent leak.

The changes are focused and strategic, targeting key functions responsible for constructing the gRPC payload. The bulk of the new code consists of benchmarks and tests to validate the performance improvements.

Architecture & Impact Assessment

  • What this PR accomplishes: It reduces the number of memory allocations performed by the gRPC middleware during request processing. This leads to lower garbage collector (GC) pressure, resulting in reduced CPU usage and potentially lower latency.

  • Key technical changes introduced:

    • Conditional Allocation: Struct fields in coprocess.SessionState are now allocated on-demand, preventing the creation of empty objects.
    • Pre-allocation: Slices are initialized with a known capacity to prevent re-allocations and copying as they grow.
    • Elimination of Empty Collections: Maps and slices in coprocess.MiniRequestObject are no longer initialized if they are empty, relying on the nil default.
  • Affected system components: The changes affect the CoProcess (gRPC) middleware within the Tyk Gateway. The core logic of the middleware remains unchanged, but its performance characteristics are improved. No other gateway components are directly impacted.

Visualization

The following diagram illustrates the components affected by the optimizations:

graph TD
    subgraph tyk_gateway [Tyk Gateway]
        A[HTTP Request Received] --> B{CoProcess Middleware Enabled?};
        B -->|Yes| C[BuildObject];
        C --> D[ProtoSessionState];
        D --> E[Create gRPC Payload];
        E --> F[Dispatch to gRPC Server];
        B -->|No| G[Continue Gateway Flow];
    end

    subgraph pr_optimizations ["PR Optimizations"]
        C --|Avoids empty map/slice allocations for<br/>SetHeaders, DeleteHeaders, etc.|--> C;
        D --|Conditionally allocates BasicAuthData, JWTData, etc.<br/>Pre-allocates slice capacities|--> D;
    end

    style C fill:#c9f,stroke:#333,stroke-width:2px
    style D fill:#c9f,stroke:#333,stroke-width:2px
Loading

Scope Discovery & Context Expansion

  • The optimizations are confined to the data marshalling process that prepares request and session data to be sent to an external gRPC service. The core functions modified are BuildObject and ProtoSessionState.
  • The changes in ProtoSessionState directly relate to the conversion of the gateway's internal user.SessionState struct into its protobuf equivalent. Understanding the structure of user.SessionState is key to appreciating the impact of these changes.
  • The addition of BenchmarkGRPCDispatch_MemoryOverhead provides a concrete way to measure the performance gains from these optimizations and guard against future regressions.
  • The TestGRPCDispatch_MemoryLeakCheck test addresses concerns about high memory usage by providing a mechanism to distinguish between a memory leak (unbounded growth) and memory churn (high allocation rate but stable heap after GC).
Metadata
  • Review Effort: 2 / 5
  • Primary Label: enhancement

Powered by Visor from Probelabs

Last updated: 2026-04-13T19:39:33.338Z | Triggered by: pr_updated | Commit: a3a2560

💡 TIP: You can chat with Visor using /visor ask <your question>

@probelabs
Copy link
Copy Markdown
Contributor Author

probelabs bot commented Apr 13, 2026

✅ Security Check Passed

No security issues found – changes LGTM.

Architecture Issues (1)

Severity Location Issue
🟠 Error contract:0
Output schema validation failed: must have required property 'issues'

✅ Performance Check Passed

No performance issues found – changes LGTM.


Powered by Visor from Probelabs

Last updated: 2026-04-13T19:39:04.851Z | Triggered by: pr_updated | Commit: a3a2560

💡 TIP: You can chat with Visor using /visor ask <your question>

@probelabs probelabs bot changed the title test: add memory leak check and benchmark for gRPC middleware perf: optimize memory allocations in CoProcess middleware Apr 13, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🚨 Jira Linter Failed

Commit: a3a2560
Failed at: 2026-04-13 19:38:12 UTC

The Jira linter failed to validate your PR. Please check the error details below:

🔍 Click to view error details
failed to validate branch and PR title rules: branch name 'fix/grpc-memory-leak-test' must contain a valid Jira ticket ID (e.g., ABC-123)

Next Steps

  • Ensure your branch name contains a valid Jira ticket ID (e.g., ABC-123)
  • Verify your PR title matches the branch's Jira ticket ID
  • Check that the Jira ticket exists and is accessible

This comment will be automatically deleted once the linter passes.

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
75.0% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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