Skip to content

fix(runner): makes PreProcessTarget concurrent#1556

Merged
Mzack9999 merged 1 commit intodevfrom
dwisiswant0/fix/runner/makes-PreProcessTargets-concurrent
Sep 24, 2025
Merged

fix(runner): makes PreProcessTarget concurrent#1556
Mzack9999 merged 1 commit intodevfrom
dwisiswant0/fix/runner/makes-PreProcessTargets-concurrent

Conversation

@dwisiswant0
Copy link
Copy Markdown
Member

@dwisiswant0 dwisiswant0 commented Sep 21, 2025

by launching goroutines.

*Runner.PreProcessTargets prev executed work
inline, so sizedwaitgroup's Add() blocking
effectively serialized target processing.

Prefixing the worker with go restores true
concurrency capped by Threads opt.

hyperfine --warmup=5 --prepare='sleep 2' \
  './naabu-75db5d2 -silent -duc -l=/tmp/apple.com-1000.txt -p=80 -c=100 -warm-up-time=0' \
  './naabu-pr-1555 -silent -duc -l=/tmp/apple.com-1000.txt -p=80 --dns-concurrency=100 -warm-up-time=0' \
  './naabu -silent -duc -l=/tmp/apple.com-1000.txt -p=80 -c=100 -warm-up-time=0'
Benchmark 1: ./naabu-75db5d2 -silent -duc -l=/tmp/apple.com-1000.txt -p=80 -c=100 -warm-up-time=0
  Time (mean ± σ):     14.288 s ±  0.807 s    [User: 0.354 s, System: 0.331 s]
  Range (min … max):   13.863 s … 16.512 s    10 runs
 
  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.
 
Benchmark 2: ./naabu-pr-1555 -silent -duc -l=/tmp/apple.com-1000.txt -p=80 --dns-concurrency=100 -warm-up-time=0
  Time (mean ± σ):     13.950 s ±  0.761 s    [User: 0.379 s, System: 0.362 s]
  Range (min … max):   13.354 s … 15.997 s    10 runs
 
Benchmark 3: ./naabu -silent -duc -l=/tmp/apple.com-1000.txt -p=80 -c=100 -warm-up-time=0
  Time (mean ± σ):      5.186 s ±  1.056 s    [User: 0.286 s, System: 0.272 s]
  Range (min … max):    3.377 s …  6.953 s    10 runs
 
  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.
 
Summary
  ./naabu -silent -duc -l=/tmp/apple.com-1000.txt -p=80 -c=100 -warm-up-time=0 ran
    2.69 ± 0.57 times faster than ./naabu-pr-1555 -silent -duc -l=/tmp/apple.com-1000.txt -p=80 --dns-concurrency=100 -warm-up-time=0
    2.75 ± 0.58 times faster than ./naabu-75db5d2 -silent -duc -l=/tmp/apple.com-1000.txt -p=80 -c=100 -warm-up-time=0

Note

./naabu-75db5d2 (dev) -- Fix host discovery (#1553)
./naabu-pr-1555 -- PR #1555.
./naabu -- this patch.

Fixes #1540

Summary by CodeRabbit

  • Refactor
    • Optimized target processing to run in parallel, reducing wait times when working with many targets. Users should see faster execution in workflows that involve adding or pre-processing multiple targets.
    • No user-facing behavior changes or configuration updates required. This update is backward-compatible and does not alter commands or output, only overall responsiveness.

by launching goroutines.

`*Runner.PreProcessTargets` prev executed work
inline, so sizedwaitgroup's `Add()` blocking
effectively serialized target processing.

Prefixing the worker with `go` restores true
concurrency capped by `Threads` opt.

Signed-off-by: Dwi Siswanto <git@dw1.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Sep 21, 2025

Walkthrough

PreProcessTargets now processes each target concurrently by launching a goroutine per target and synchronizing with an existing WaitGroup. The internal AddTarget invocation remains, but execution is parallelized across targets. No exported function signatures were modified.

Changes

Cohort / File(s) Summary
Concurrent target preprocessing
pkg/runner/targets.go
Changed per-target processing from inline synchronous execution to per-target goroutines using wg.Add/wg.Done, enabling parallel AddTarget calls during PreProcessTargets.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant Runner
  participant WG as WaitGroup
  participant T1 as Goroutine(Target 1)
  participant Tn as Goroutine(Target N)
  participant Add as AddTarget

  Caller->>Runner: PreProcessTargets(targets)
  Runner->>WG: Add(len(targets))
  loop for each target
    Runner->>T1: spawn go func(target)
    T1->>Add: AddTarget(target)
    T1-->>WG: Done()
    Runner->>Tn: spawn go func(target)
    Tn->>Add: AddTarget(target)
    Tn-->>WG: Done()
  end
  Runner->>WG: Wait()
  WG-->>Runner: all done
  Runner-->>Caller: return
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • Mzack9999

Poem

A hop, a skip, a thread per host—
I twitch my nose and spawn a ghost.
Goroutines race, DNS in flight,
WaitGroup drums to sync the night.
Ports to scan, horizons wide—
Concurrency’s my carrot ride! 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title concisely states the primary intent—making the runner's PreProcessTargets logic concurrent—and uses conventional commit syntax, so it accurately reflects the main change in the patch. The only minor nitpick is the title uses the singular "PreProcessTarget" while the code and PR description refer to "PreProcessTargets", but this does not obscure the intent.
Linked Issues Check ✅ Passed The change converts per-target processing in Runner.PreProcessTargets to spawn worker goroutines while retaining WaitGroup synchronization and capping concurrency via the Threads option, which directly addresses the linked issue [#1540] reporting sequential DNS resolution; the included benchmarks further support the performance improvement. No exported signatures were changed and the modification specifically targets the target preprocessing path, so the coding objective of enabling DNS-resolution concurrency appears satisfied.
Out of Scope Changes Check ✅ Passed Only pkg/runner/targets.go was modified to change per-target processing to launch goroutines and no other files or exported APIs were altered, so there are no apparent out-of-scope or unrelated changes in this patch. The change is focused and aligned with the linked issue and PR objectives.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dwisiswant0/fix/runner/makes-PreProcessTargets-concurrent

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/runner/targets.go (1)

106-115: Enforce Threads >= 1 — sizedwaitgroup.New(size <= 0) uses math.MaxInt32 (practically unbounded)

pkg/runner/targets.go (lines 106–115) launches a goroutine per scanned target with wg.Add(); sizedwaitgroup.New(size <= 0) sets the limit to math.MaxInt32 (≈2^31), enabling effectively-unbounded concurrency. Clamp/validate Threads to a positive sane default before creating the sizedwaitgroup (e.g., if Threads <= 0 { Threads = 1 }).

🧹 Nitpick comments (2)
pkg/runner/targets.go (2)

117-119: Handle scanner errors after the loop

bufio.Scanner errors (e.g., token too long, I/O) are currently ignored. Check s.Err() after Wait() and return it.

Apply this diff:

   wg.Wait()
+  if err := s.Err(); err != nil {
+    return err
+  }
   return nil

96-96: Optional: guard Threads to sane bounds

If Threads can be 0/negative (interpreted as unlimited) or extremely large, consider clamping to [1, some upper cap] to avoid DNS flood and goroutine storms.

Example:

+ import "runtime"
@@
- wg := sizedwaitgroup.New(r.options.Threads)
+ threads := r.options.Threads
+ if threads <= 0 {
+   threads = runtime.GOMAXPROCS(0)
+ }
+ if threads > 4096 {
+   threads = 4096
+ }
+ wg := sizedwaitgroup.New(threads)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75db5d2 and 0faa1b7.

📒 Files selected for processing (1)
  • pkg/runner/targets.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: build-windows
  • GitHub Check: build-mac
  • GitHub Check: build-linux
  • GitHub Check: Functional Test (ubuntu-latest)
  • GitHub Check: Lint Test
  • GitHub Check: release-test-linux
  • GitHub Check: release-test-windows
  • GitHub Check: Analyze (go)
🔇 Additional comments (2)
pkg/runner/targets.go (2)

121-218: Verify thread-safety of IPRanger mutations

pkg/runner/targets.go (AddTarget) now calls IPRanger.Contains, AddHostWithMetadata and Np.ValidateAddress concurrently. IPRanger implementation was not found in the repo, so cannot confirm these methods are goroutine-safe — verify that Contains/AddHostWithMetadata and Np.ValidateAddress are concurrency-safe; if not, add internal locking (sync.Mutex / sync.RWMutex) or funnel all mutations through a single worker/channel.


93-96: Close is safe — PreProcessTargets is the sole producer

All sends to r.streamChannel are inside pkg/runner/targets.go (lines 134, 143, 156, 189, 191, 197). PreProcessTargets waits for worker goroutines (wg.Wait at line 117) before returning, so defer close(r.streamChannel) runs after all sends complete; no other producers found in repo.

Copy link
Copy Markdown
Member

@Mzack9999 Mzack9999 left a comment

Choose a reason for hiding this comment

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

nice catch!

@Mzack9999 Mzack9999 merged commit 5bb71e6 into dev Sep 24, 2025
13 checks passed
@Mzack9999 Mzack9999 deleted the dwisiswant0/fix/runner/makes-PreProcessTargets-concurrent branch September 24, 2025 19:04
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.

Concurancy not working for DNS Resolution

2 participants