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

client struct: lazy init components and optimize struct layout #1405

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

Conversation

uriyage
Copy link
Contributor

@uriyage uriyage commented Dec 8, 2024

Refactor client structure to use modular data components

Current State

The client structure allocates memory for replication / pubsub / multi-keys / module / blocked data for every client, despite these features being used by only a small subset of clients. In addition the current field layout in the client struct is suboptimal, with poor alignment and unnecessary padding between fields, leading to a larger than necessary memory footprint of 896 bytes per client. Furthermore, fields that are frequently accessed together during operations are scattered throughout the struct, resulting in poor cache locality.

This PR's Change

  1. Lazy Initialization
  • Components are only allocated when first used:
    • PubSubData: Created on first SUBSCRIBE/PUBLISH operation
    • ReplicationData: Initialized only for replica connections
    • ModuleData: Allocated when module interaction begins
    • BlockingState: Created when first blocking command is issued
    • MultiState: Initialized on MULTI command
  1. Memory Layout Optimization:

    • Grouped related fields for better locality
    • Moved rarely accessed fields (e.g., client->name) to struct end
    • Optimized field alignment to eliminate padding
  2. Additional changes:

    • Moved watched_keys to be static allocated in the mstate struct
    • Relocated replication init logic to replication.c

Key Benefits

  • Efficient Memory Usage:
  • 45% smaller base client structure - Basic clients now use 528 bytes (down from 896).
  • Better memory locality for related operations
  • Performance improvement in high throughput scenarios. No performance regressions in other cases.

Performance Impact

Tested with 650 clients and 512 bytes values.

Single Thread Performance

Operation Dataset New (ops/sec) Old (ops/sec) Change %
SET 1 key 261,799 258,261 +1.37%
SET 3M keys 209,134 ~209,000 ~0%
GET 1 key 281,564 277,965 +1.29%
GET 3M keys 231,158 228,410 +1.20%

8 IO Threads Performance

Operation Dataset New (ops/sec) Old (ops/sec) Change %
SET 1 key 1,331,578 1,331,626 -0.00%
SET 3M keys 1,254,441 1,152,645 +8.83%
GET 1 key 1,293,149 1,289,503 +0.28%
GET 3M keys 1,152,898 1,101,791 +4.64%

Pipeline Performance (3M keys)

Operation Pipeline Size New (ops/sec) Old (ops/sec) Change %
SET 10 548,964 538,498 +1.94%
SET 20 606,148 594,872 +1.89%
SET 30 631,122 616,606 +2.35%
GET 10 628,482 624,166 +0.69%
GET 20 687,371 681,659 +0.84%
GET 30 725,855 721,102 +0.66%

Observations:

  1. Single-threaded operations show consistent improvements (1-1.4%)
  2. Multi-threaded performance shows significant gains for large datasets:
    • SET with 3M keys: +8.83% improvement
    • GET with 3M keys: +4.64% improvement
  3. Pipeline operations show consistent improvements:
    • SET operations: +1.89% to +2.35%
    • GET operations: +0.66% to +0.84%
  4. No performance regressions observed in any test scenario

Related issue:#761

Copy link

codecov bot commented Dec 8, 2024

Codecov Report

Attention: Patch coverage is 87.87313% with 65 lines in your changes missing coverage. Please review.

Project coverage is 70.84%. Comparing base (f20d629) to head (618c9eb).

Files with missing lines Patch % Lines
src/module.c 4.08% 47 Missing ⚠️
src/replication.c 94.55% 11 Missing ⚠️
src/networking.c 93.54% 4 Missing ⚠️
src/rdb.c 50.00% 2 Missing ⚠️
src/blocked.c 98.38% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #1405      +/-   ##
============================================
+ Coverage     70.81%   70.84%   +0.03%     
============================================
  Files           118      118              
  Lines         63561    63596      +35     
============================================
+ Hits          45010    45056      +46     
+ Misses        18551    18540      -11     
Files with missing lines Coverage Δ
src/acl.c 88.83% <100.00%> (ø)
src/aof.c 80.21% <100.00%> (+0.08%) ⬆️
src/cluster.c 88.51% <100.00%> (ø)
src/cluster_legacy.c 86.67% <100.00%> (-0.04%) ⬇️
src/multi.c 97.30% <100.00%> (+0.87%) ⬆️
src/pubsub.c 96.77% <100.00%> (-0.27%) ⬇️
src/script.c 87.69% <100.00%> (+0.04%) ⬆️
src/server.c 87.42% <100.00%> (+0.02%) ⬆️
src/server.h 100.00% <ø> (ø)
src/timeout.c 90.00% <100.00%> (ø)
... and 6 more

... and 7 files with indirect coverage changes

@zuiderkwast
Copy link
Contributor

  • 45% smaller base client structure - Basic clients now use 528 bytes (down from 896).

Amazing!

@zuiderkwast zuiderkwast self-requested a review December 9, 2024 10:29
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.

2 participants