Skip to content

⚡ [Optimize IOBufferPool eviction map lookups]#286

Open
segin wants to merge 1 commit intomasterfrom
perf-bufferpool-eviction-17916129341220046635
Open

⚡ [Optimize IOBufferPool eviction map lookups]#286
segin wants to merge 1 commit intomasterfrom
perf-bufferpool-eviction-17916129341220046635

Conversation

@segin
Copy link
Copy Markdown
Owner

@segin segin commented Apr 8, 2026

💡 What: Replaced an unnecessary m_pools.find(buffer_size) lookup inside the buffer pool eviction loop. We now cache a pointer to the PoolEntry directly in an EfficiencyData struct during the initial analysis loop, allowing O(1) direct access during the eviction step. We also call .reserve() on the vector to avoid reallocations.

🎯 Why: optimizeAllocationPatterns evaluates buffer statistics and evicts inefficient pools. The map m_pools was being iterated over to collect stats, and then looked up again using m_pools.find() for the eviction candidates. This resulted in an avoidable O(log N) overhead per eviction. Since the operation happens while holding an exclusive lock, preserving and using a raw pointer is safe and significantly faster.

📊 Measured Improvement:
Created a standalone benchmark simulating the iteration over 1,000 pool entries, running 100,000 passes of eviction candidate selection.

  • Baseline (avg): 904,624 us
  • Optimized (avg): 788,906 us
  • Speedup: ~1.15x improvement on the optimization routine's inner loop.

PR created automatically by Jules for task 17916129341220046635 started by @segin

Modified `optimizeAllocationPatterns` in `src/io/BufferPool.cpp` to cache a raw pointer to the `PoolEntry` alongside its size and efficiency score during the initial scan of `m_pools`. This avoids a redundant O(log N) `std::map::find` call inside the eviction loop.

Also preallocated the size-efficiency vector using `reserve()` to reduce allocation overhead.

Co-authored-by: segin <480709+segin@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings April 8, 2026 23:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Optimizes IOBufferPool::optimizeAllocationPatterns() by avoiding redundant m_pools.find() lookups during eviction candidate processing, reducing overhead while the pool map is exclusively locked.

Changes:

  • Cache PoolEntry* alongside size/efficiency during the analysis pass to enable O(1) access during eviction.
  • Reserve capacity for the efficiency vector to avoid repeated reallocations.
  • Add a standalone benchmark to compare baseline vs optimized eviction-candidate processing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/io/BufferPool.cpp Stores direct PoolEntry* in the efficiency list and reserves vector capacity to speed up the eviction loop.
tests/benchmark_buffer_pool_eviction.cpp Adds a microbenchmark intended to measure the impact of removing the extra map lookup (and vector reallocation).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +23
double run_baseline(std::map<size_t, std::shared_ptr<PoolEntry>>& m_pools) {
auto start_baseline = std::chrono::high_resolution_clock::now();
size_t total_evicted_baseline = 0;
for (int it = 0; it < ITERATIONS; ++it) {
std::vector<std::pair<size_t, double>> size_efficiency;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

total_evicted_baseline is never used after being incremented, so with optimizations enabled the compiler may treat the eviction loop work as dead code and remove/hoist it, making the timing numbers unreliable. Consider consuming the value (e.g., return it, print it, or feed it into a volatile/optimization barrier) so the baseline path can’t be optimized away.

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +48
double run_optimized(std::map<size_t, std::shared_ptr<PoolEntry>>& m_pools) {
auto start_optimized = std::chrono::high_resolution_clock::now();
size_t total_evicted_optimized = 0;
for (int it = 0; it < ITERATIONS; ++it) {
struct EfficiencyData {
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

Same benchmarking issue as the baseline: total_evicted_optimized is incremented but never consumed, so the compiler may optimize away some/all of the work inside the timed region. Please ensure the optimized code path has an observable result (e.g., return/print the counter or use a volatile sink) so the benchmark measures the intended operations.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request optimizes the IOBufferPool::optimizeAllocationPatterns function by replacing redundant map lookups with direct pointers to PoolEntry objects within a new EfficiencyData struct. Additionally, it improves performance by pre-allocating memory for the efficiency tracking vector and includes a benchmark test to validate the speedup. I have no feedback to provide.

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