Skip to content

[performance-profiler] Optimize Network.Check single-IP path to reduce allocations and CPU #49574

@github-actions

Description

@github-actions

Hot Path

libbeat/conditions/network.go in (*Network).Check currently calls extractIP for every event value and then scans the returned slice.

Relevant code paths:

  • libbeat/conditions/network.go:153-209 (Check)
  • libbeat/conditions/network.go:208-225 (extractIP)
  • Benchmark: libbeat/conditions/network_test.go:301-323 (BenchmarkNetworkCondition)

Profiling Data

Before:

go test ./libbeat/conditions -run '^$' -bench '^BenchmarkNetworkCondition$' -benchmem -count=10

BenchmarkNetworkCondition-4   6691453   181.8 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   5696349   182.5 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6652167   180.4 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6576028   180.7 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6604658   181.2 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6624548   182.5 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6617449   180.4 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6587047   180.8 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6591918   183.1 ns/op   40 B/op   2 allocs/op
BenchmarkNetworkCondition-4   6225799   180.5 ns/op   40 B/op   2 allocs/op

Proposed Change

Avoid per-call slice construction in the common single-IP path by handling concrete types directly in Check:

  • Fast-path string and net.IP without building []net.IP.
  • Keep loop semantics for []string and []net.IP.
  • Preserve behavior for invalid/empty values.

Representative diff:

- ipList := extractIP(value)
- if len(ipList) == 0 { ... }
- if !slices.ContainsFunc(ipList, network.Contains) { ... }
+ switch v := value.(type) {
+ case string:
+   if !network.Contains(net.ParseIP(v)) { return false }
+ case net.IP:
+   if !network.Contains(v) { return false }
+ case []net.IP:
+   // any-match loop
+ case []string:
+   // parse + any-match loop
+ default:
+   return false
+ }

Results

After:

go test ./libbeat/conditions -run '^$' -bench '^BenchmarkNetworkCondition$' -benchmem -count=10

BenchmarkNetworkCondition-4   8108420   141.5 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8422035   141.3 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8605186   139.9 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8111130   142.6 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8505433   142.3 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8527528   141.4 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8518203   147.3 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8579733   142.4 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8500126   141.1 ns/op   16 B/op   1 allocs/op
BenchmarkNetworkCondition-4   8486481   140.2 ns/op   16 B/op   1 allocs/op

Improvement:

  • Time: ~22% faster (about 181 ns/op -> 141 ns/op)
  • Memory: 60% less bytes/op (40 -> 16)
  • Allocations: 50% fewer allocs/op (2 -> 1)

Verification

  • Tests run: go test ./libbeat/conditions -run '^TestNetwork'
  • Result: pass
  • Behavior preservation: same network matching semantics for string, net.IP, []string, and []net.IP; invalid values still fail.

Evidence

Commands run:

  • go test ./libbeat/conditions -run '^$' -bench '^BenchmarkNetworkCondition$' -benchmem -count=10 (before)
  • go test ./libbeat/conditions -run '^TestNetwork'
  • go test ./libbeat/conditions -run '^$' -bench '^BenchmarkNetworkCondition$' -benchmem -count=10 (after)

Duplicate check:

  • Compared against /tmp/previous-findings.json; this hot path is distinct from prior filed items (e.g., dissect suffix allocations, diskqueue decoder buffer reuse, memqueue producer allocations).

What is this? | From workflow: Performance Profiler

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

  • expires on Mar 26, 2026, 2:34 PM UTC

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs_teamIndicates that the issue/PR needs a Team:* label

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions