Skip to content

Conversation

zaidoon1
Copy link
Contributor

@zaidoon1 zaidoon1 commented Aug 31, 2025

Problem

The current C API implementation has inefficiencies that impact performance in production environments:

  1. Double allocations in Get operations: Values are first copied into a std::string, then copied again into a malloc'd buffer
  2. Unnecessary string temporaries: Using std::string as intermediate storage adds allocation/deallocation overhead
  3. No zero-copy read path: All read operations require at least one allocation and copy
  4. Redundant operations: CopyString performed unnecessary sizeof(char) multiplication

Solution

1. Use PinnableSlice for Get Operations

  • Before: DB::Get() → std::string → malloc'd buffer (2 allocations, 2 copies)
  • After: DB::Get() → PinnableSlice → malloc'd buffer (1 allocation, 1 copy)
  • Impact: 50% reduction in allocations and copies

2. Optimize CopyString Helper

  • Removed redundant sizeof(char) multiplication
  • Single implementation using Slice parameter (works with all types via implicit conversion)
  • Added inline for better optimization

3. New Zero-Copy API Functions

Added high-performance alternatives for allocation-sensitive workloads:

  • rocksdb_get_pinned_v2/ rocksdb_get_pinned_cf_v2 - Zero-copy read access
  • rocksdb_get_into_buffer/ rocksdb_get_into_buffer_cf - Copy into user-provided buffer
  • rocksdb_pinnable_handle_* - Handle management functions

Performance Improvements

Operation Allocations Improvement
rocksdb_get 2 → 1 50% reduction
rocksdb_get_cf 2 → 1 50% reduction
rocksdb_multi_get (per key) 2 → 1 50% reduction
rocksdb_transaction_get 2 → 1 50% reduction
rocksdb_writebatch_wi_get_from_batch 2 → 1 50% reduction
rocksdb_get_pinned_v2 (new) 0 100% reduction

Functions Optimized (30+)

  • All Get variants (regular, CF, with timestamps)
  • All MultiGet variants
  • All Transaction Get/MultiGet operations
  • All WriteBatch Get operations
  • KeyMayExist operations
  • Metadata getters (column family names, SST file keys, transaction names, DB identity)

Testing

  • Added tests for new zero-copy functions
  • Added tests for previously untested functions rocksdb_column_family_handle_get_name, rocksdb_transaction_get_name

Migration Path

Applications can adopt improvements in three ways:

  1. No changes needed - Existing code automatically benefits from 50% allocation reduction
  2. Incremental adoption - Replace hot-path calls with zero-copy variants
  3. Full optimization - Use rocksdb_get_into_buffer

@meta-cla meta-cla bot added the CLA Signed label Aug 31, 2025
@zaidoon1 zaidoon1 force-pushed the zaidoon/c-api-perf branch 2 times, most recently from b9789d8 to 60fbbf7 Compare August 31, 2025 14:51
@zaidoon1 zaidoon1 changed the title optimize Get operations by removing CopyString and using PinnableSlice for zero-copy reads optimize C API to reduce memory allocations and using PinnableSlice for zero-copy reads Aug 31, 2025
@zaidoon1 zaidoon1 force-pushed the zaidoon/c-api-perf branch from 60fbbf7 to 9c57aea Compare August 31, 2025 14:59
@zaidoon1
Copy link
Contributor Author

zaidoon1 commented Sep 2, 2025

@cbi42 would be great if you can take a look at this when you can. Thanks!

@zaidoon1
Copy link
Contributor Author

zaidoon1 commented Sep 8, 2025

@cbi42 bumping this, can you please take a look. Also cc @pdillinger

@zaidoon1
Copy link
Contributor Author

@cbi42 did you get a chance to take a look at this? What do you think? If you think it's a bad change or won't work as I expect, please let me know

@zaidoon1
Copy link
Contributor Author

@pdillinger what do you think about this change? is it worth doing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant