Skip to content

⚡ Bolt: Batch producer wakeups outside spinlock - #35

Open
maxugly wants to merge 1 commit into
mainfrom
bolt-batch-producer-wakeup-8805218265237772964
Open

⚡ Bolt: Batch producer wakeups outside spinlock#35
maxugly wants to merge 1 commit into
mainfrom
bolt-batch-producer-wakeup-8805218265237772964

Conversation

@maxugly

@maxugly maxugly commented Aug 1, 2026

Copy link
Copy Markdown
Owner

💡 What: Move the call to nata_wake_tx_peer outside of the per-packet spin_lock loop during NAPI polling (nata_poll). It is now batched and called at most once per budget if any slots were freed.

🎯 Why: Calling netif_wake_queue (inside nata_wake_tx_peer) inside a spinlock while iterating through a batch of up to budget packets creates significant lock contention and friction. The peer is repeatedly woken up for single slots while the consumer still holds the lock it needs to enqueue. Deferring the wakeup until the batch finishes reduces CPU overhead and lock bouncing, allowing the producer to wake up and push larger batches into multiple freed slots.

📊 Impact: Expected to lower CPU utilization under heavy packet load and potentially increase end-to-end throughput by reducing the number of lock acquisitions and queue wakeups per packet.

🔬 Measurement:

  1. Build the module: make -C module
  2. Run standard benchmarking: sudo ./scripts/nata-bench-once.sh
  3. Compare TCP throughput (iperf3) and top CPU utilization in nata_poll against baseline.

PR created automatically by Jules for task 8805218265237772964 started by @maxugly

Summary by CodeRabbit

  • Performance Improvements
    • Improved network polling efficiency by batching transmit queue wakeups.
    • Reduced lock contention during packet processing, helping improve throughput and responsiveness.

By deferring the netif_wake_queue() call until after the NAPI RX polling
loop has dequeued a batch of packets, we eliminate redundant wakeup calls
and drastically reduce spinlock contention on the shared ring buffers.

Co-authored-by: maxugly <64644401+maxugly@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.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

nata_poll now batches peer TX queue wakeups. It counts freed RX slots while holding the spinlock, then performs one wakeup after releasing the lock. A learning entry documents this pattern.

Changes

NAPI wakeup batching

Layer / File(s) Summary
Batch RX reclamation and peer wakeup
.jules/bolt.md, module/nata_net.c
nata_poll tracks freed RX slots during locked dequeue processing. It wakes the peer TX queue once outside the spinlock when slots were freed. The learning entry documents the batching pattern.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • maxugly/nata#3: Both changes modify nata_poll to reduce spinlock-related overhead.
  • maxugly/nata#31: Both changes batch TX peer wakeups outside the spinlock.
  • maxugly/nata#33: Both changes batch producer wakeups outside the ring-buffer spinlock.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes batching producer wakeups outside the spinlock, which is the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bolt-batch-producer-wakeup-8805218265237772964

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

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
module/nata_net.c (1)

53-56: 🚀 Performance & Scalability | 🔵 Trivial

Record datapath verification before merge.

Build the module and compare baseline and new TCP throughput and CPU utilization under the relevant load. Record the results. State any inability to run privileged or dual-host tests.

As per coding guidelines, run relevant verification for touched layers and update performance documentation when the design changes or measured results shift by more than 15%.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@module/nata_net.c` around lines 53 - 56, After updating the batch producer
wakeup in nata_wake_tx_peer, build the module and benchmark baseline versus new
TCP throughput and CPU utilization under the relevant load. Record the results,
note any inability to run privileged or dual-host tests, and update performance
documentation if the design changes or measurements differ by more than 15%.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.jules/bolt.md:
- Around line 9-12: Update the owning as-built specification section covering
NAPI polling and RX slot reclamation to state that slots are freed during
polling and nata_wake_tx_peer is invoked once after the batch, outside
priv->lock. Preserve the existing learning entry in .jules/bolt.md as supporting
rationale and document this locking/timing footgun in the nearest specification.

In `@module/nata_net.c`:
- Around line 30-42: Update the slot accounting in the loop containing
sim_rx_dequeue so slots_freed is incremented only when a slot was actually
consumed: track a separate consumed-slot result or handle exactly return values
1, -EINVAL, and -ENOMEM. Exclude -ENODEV, which returns before clearing a slot,
and preserve the existing dequeue and locking flow.

---

Nitpick comments:
In `@module/nata_net.c`:
- Around line 53-56: After updating the batch producer wakeup in
nata_wake_tx_peer, build the module and benchmark baseline versus new TCP
throughput and CPU utilization under the relevant load. Record the results, note
any inability to run privileged or dual-host tests, and update performance
documentation if the design changes or measurements differ by more than 15%.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a33d6e5-50ef-433f-8efe-3288d2c80178

📥 Commits

Reviewing files that changed from the base of the PR and between 6d5b3ed and dd8a14b.

📒 Files selected for processing (2)
  • .jules/bolt.md
  • module/nata_net.c

Comment thread .jules/bolt.md
Comment on lines +9 to +12

## 2026-08-01 - Batch Producer Wakeups Outside Spinlock
**Learning:** Calling `netif_wake_queue` (via `nata_wake_tx_peer`) inside a spinlock during the NAPI polling loop causes significant lock contention. A single poll could wake the peer multiple times for individual packets while holding the lock that the peer needs to enqueue, creating unnecessary friction.
**Action:** Always batch producer wakeups outside of the spinlock loop in NAPI polling contexts (e.g., using a `slots_freed` tracker).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Update the owning as-built specification.

This learning entry records the rationale, but docs/specs/04-kernel-module.md:173-184 must also describe the implemented timing: RX slots are freed during polling, and nata_wake_tx_peer runs once after the batch and outside priv->lock. Keep this entry as supporting rationale.

As per coding guidelines, perform a DOX/documentation pass after every meaningful behavior change and document footguns in the nearest as-built specification.

🧰 Tools
🪛 LanguageTool

[style] ~12-~12: This phrase is redundant. Consider using “outside”.
Context: ...Action:** Always batch producer wakeups outside of the spinlock loop in NAPI polling conte...

(OUTSIDE_OF)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.jules/bolt.md around lines 9 - 12, Update the owning as-built specification
section covering NAPI polling and RX slot reclamation to state that slots are
freed during polling and nata_wake_tx_peer is invoked once after the batch,
outside priv->lock. Preserve the existing learning entry in .jules/bolt.md as
supporting rationale and document this locking/timing footgun in the nearest
specification.

Source: Coding guidelines

Comment thread module/nata_net.c
Comment on lines +30 to +42
int slots_freed = 0;

while (work < budget) {
struct sk_buff *skb = NULL;
int ret;

spin_lock(&priv->lock);
ret = sim_rx_dequeue(priv, is_dev0, &skb);
if (ret != 0)
nata_wake_tx_peer(priv, is_dev0);
spin_unlock(&priv->lock);

if (ret != 0)
slots_freed++;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not infer slot reclamation from ret != 0.

sim_rx_dequeue() returns -ENODEV before it reads or clears a slot (module/nata_blk.c, sim_rx_dequeue). Therefore, a nonzero result does not always return producer capacity. Use a separate consumed-slot flag, or handle only the current consuming results (1, -EINVAL, and -ENOMEM). Do not replace this with ret > 0, because the two negative paths also free slots.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@module/nata_net.c` around lines 30 - 42, Update the slot accounting in the
loop containing sim_rx_dequeue so slots_freed is incremented only when a slot
was actually consumed: track a separate consumed-slot result or handle exactly
return values 1, -EINVAL, and -ENOMEM. Exclude -ENODEV, which returns before
clearing a slot, and preserve the existing dequeue and locking flow.

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