Skip to content

perf(catalog): split exact matches & pattern - #7340

Merged
Mzack9999 merged 4 commits into
projectdiscovery:devfrom
mikhail5555:feature/improved-filter-performance
Apr 29, 2026
Merged

perf(catalog): split exact matches & pattern#7340
Mzack9999 merged 4 commits into
projectdiscovery:devfrom
mikhail5555:feature/improved-filter-performance

Conversation

@mikhail5555

@mikhail5555 mikhail5555 commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Reason for change:
image

Proposed changes

Instead of treating IDs (and ExcludedIDs) as both 'exact' matches and pattern matches, I now pre-compile a list and split them out.
Especially for a high list of 'exact matches' the performance with the current implementation is extremely taxing, for the following reasons:

  1. For each existing template (N) it checks all included IDs (M) O(N*M). Given that N is in the order of 10_000, this make it very expensive if you want to run on a small subset of them (say 1_000 IDs).
  2. Each ID is treated as an pattern, making it very cpu expensive to have many ID filters.

Fixes:

  1. Convert slices.Contains into a map lookup to speedup lookup drastically.
  2. Filter out IDs that contain a pattern, to be checked individually, but only after exact matches checks.

Proof

goos: darwin
goarch: arm64
pkg: github.com/projectdiscovery/nuclei/v3/pkg/catalog/index
cpu: Apple M1 Pro
BenchmarkFilterMatches_Mixed
BenchmarkFilterMatches_Mixed/ids=10,patterns=0
BenchmarkFilterMatches_Mixed/ids=10,patterns=0-10         	    4730	    236437 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed/ids=100,patterns=0
BenchmarkFilterMatches_Mixed/ids=100,patterns=0-10        	    4096	    299793 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed/ids=1000,patterns=0
BenchmarkFilterMatches_Mixed/ids=1000,patterns=0-10       	    4863	    245167 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed/ids=100,patterns=1
BenchmarkFilterMatches_Mixed/ids=100,patterns=1-10        	    1766	    675314 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed/ids=100,patterns=3
BenchmarkFilterMatches_Mixed/ids=100,patterns=3-10        	     784	   1530580 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed/ids=100,patterns=5
BenchmarkFilterMatches_Mixed/ids=100,patterns=5-10        	     537	   2229378 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed_Old
BenchmarkFilterMatches_Mixed_Old/ids=10,patterns=0
BenchmarkFilterMatches_Mixed_Old/ids=10,patterns=0-10     	     133	   8941001 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=0
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=0-10    	      13	  89216647 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed_Old/ids=1000,patterns=0
BenchmarkFilterMatches_Mixed_Old/ids=1000,patterns=0-10   	       2	 879078188 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=1
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=1-10    	      13	  89648577 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=3
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=3-10    	      12	  91140938 ns/op	       0 B/op	       0 allocs/op
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=5
BenchmarkFilterMatches_Mixed_Old/ids=100,patterns=5-10    	      12	  92591368 ns/op	       0 B/op	       0 allocs/op

Especially when using many 'exact' IDs (aka not patterns), the improvement is drastic (3000x).

  • BenchmarkFilterMatches_Mixed/ids=1000,patterns=0 245167 ns/op
  • BenchmarkFilterMatches_Mixed_Old/ids=1000,patterns=0 879078188 ns/op

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Disclaimer

(Logic) Code is written by human, benchmark is written with AI assistance.

Summary by CodeRabbit

  • New Features

    • Filters can be pre-compiled for faster matching; matching now distinguishes exact IDs from wildcard patterns for improved performance.
    • Filter string output now includes configured exclude-ID details.
  • Tests

    • Added benchmarks measuring filter performance across varied exact/wildcard mixes and corpus sizes.
    • Updated unit tests to exercise the new compile-and-match behavior.

@auto-assign
auto-assign Bot requested a review from Mzack9999 April 13, 2026 13:53
@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Introduces a sync.Once-guarded Filter.Compile() that precomputes exact-match maps and wildcard pattern lists for include/exclude IDs; matching now uses cached helpers. Adds benchmarks exercising compiled matching and updates tests to use the new compiled matching paths. Filter.String() includes exclude-ids when set.

Changes

Cohort / File(s) Summary
Core Filter Implementation
pkg/catalog/index/filter.go
Added Compile() and sync.Once to lazily build cached maps (includeIDs, excludeIDs) and pattern slices (includeIDPatterns, excludeIDPatterns); replaced direct iteration over IDs/ExcludeIDs with matchesIncludeID()/matchesExcludeID() that use caches; removed/retired the prior matchesID usage; updated Filter.String() to include exclude-ids when present.
Benchmark Tests
pkg/catalog/index/filter_bench_test.go
New benchmark creating a ~10k metadata corpus and filters mixing exact IDs and wildcard patterns; compiles the filter and measures matching performance via matchesIncludeID, with allocation reporting enabled.
Unit Tests
pkg/catalog/index/filter_test.go
Tests refactored to build a Filter, call Compile(), and assert using matchesIncludeID() instead of the former standalone matchesID helper; minor test-case label reorder and import reordering.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through lists of IDs with care,
Split stars and questions into tidy lair.
Once called, I compile, then zip on by,
Exact maps first, patterns next—oh my!
A twitch of whiskers, faster matching flair.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 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 the main change: converting filter ID matching to use separated exact matches and patterns instead of treating all as patterns, which directly addresses the performance optimization objective.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

can be removed after review, let me know if you want me to do it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
pkg/catalog/index/filter.go (1)

187-189: Address TODO before merging.

The comment indicates this deprecated function should be removed before the PR is merged. Ensure this is cleaned up along with its usage in filter_bench_test.go (the BenchmarkFilterMatches_Mixed_Old benchmark).

Would you like me to help track this as an issue, or should the old benchmark be retained for future regression comparisons?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/index/filter.go` around lines 187 - 189, Remove the deprecated
helper and its benchmark: delete the matchesID function and any references to
it, and remove the BenchmarkFilterMatches_Mixed_Old benchmark from
filter_bench_test.go; replace callers (if any) with the supported
matchesIncludeID implementation or its test/bench variants, and ensure
tests/benches compile by updating imports/bench names accordingly so no
dead/unused symbols remain (targets: matchesID, matchesIncludeID,
BenchmarkFilterMatches_Mixed_Old).
pkg/catalog/index/filter_test.go (1)

8-11: Non-standard import grouping.

Go convention groups imports as: stdlib, blank line, external packages, blank line, internal packages. Currently testify/require is placed between stdlib and internal with an inconsistent blank line.

Suggested grouping
 import (
 	"os"
 	"path/filepath"
 	"testing"
 
-	"github.com/stretchr/testify/require"
-
 	"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
 	"github.com/projectdiscovery/nuclei/v3/pkg/templates/types"
+	"github.com/stretchr/testify/require"
 )

Or run go fmt / goimports to auto-fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/index/filter_test.go` around lines 8 - 11, The import block in
pkg/catalog/index/filter_test.go is mis-grouped: move the external package
"github.com/stretchr/testify/require" into the external imports group (after the
stdlib imports and separated by a blank line) so imports follow the stdlib |
external | internal grouping and ensure a blank line between groups; you can
also run gofmt/goimports to automatically fix the ordering and spacing in the
imports block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/catalog/index/filter_bench_test.go`:
- Around line 40-41: The benchmark comment above BenchmarkFilterMatches_Mixed is
inconsistent (says 7000 while templateCount is 10,000); update the comment to
match the actual templateCount value (or change templateCount to 7000 if
intended) so the description and the variable (templateCount) are aligned—edit
the comment text referring to the benchmark and/or adjust templateCount in the
benchmark setup to reflect the intended corpus size.

In `@pkg/catalog/index/filter.go`:
- Around line 22-23: Fix the typo in the comment for the struct field once in
pkg/catalog/index/filter.go: change "firs ttime" to "first time" so the comment
reads "once ensures that IDs and ExcludedIDs are compiled the first time Matches
is called." and keep the reference to the once sync.Once field unchanged.
- Around line 204-207: The comment on Filter.Compile is misleading about calling
Compile() manually; update the docs to state that Compile() is called
automatically on first Matches() and that Filter (including IDs and ExcludeIDs)
must be treated as immutable once compiled or when used concurrently—do not
suggest callers can safely mutate and re-run Compile concurrently. Specifically
mention Filter.Compile, Filter.Matches, and matchesIncludeID, and replace the
"If IDs or ExcludeIDs are modified after calling Matches, this must be called
manually" guidance with a clear concurrency-safe directive: callers must either
call Compile() before sharing the Filter between goroutines or never modify
IDs/ExcludeIDs after the Filter is in use.
- Around line 212-216: The pattern-detection logic in the filtering code
incorrectly treats patterns with character classes like "[...]" as exact IDs;
update the checks that currently call strings.ContainsAny(idOrPattern, "*?") to
also include '[' so character-class patterns are detected (do this where
includeIDPatterns/ includeIDs are set and likewise for excludeIDPatterns/
excludeIDs), e.g., in the branches that append to f.includeIDPatterns or
f.excludeIDPatterns instead of inserting into f.includeIDs or f.excludeIDs.

---

Nitpick comments:
In `@pkg/catalog/index/filter_test.go`:
- Around line 8-11: The import block in pkg/catalog/index/filter_test.go is
mis-grouped: move the external package "github.com/stretchr/testify/require"
into the external imports group (after the stdlib imports and separated by a
blank line) so imports follow the stdlib | external | internal grouping and
ensure a blank line between groups; you can also run gofmt/goimports to
automatically fix the ordering and spacing in the imports block.

In `@pkg/catalog/index/filter.go`:
- Around line 187-189: Remove the deprecated helper and its benchmark: delete
the matchesID function and any references to it, and remove the
BenchmarkFilterMatches_Mixed_Old benchmark from filter_bench_test.go; replace
callers (if any) with the supported matchesIncludeID implementation or its
test/bench variants, and ensure tests/benches compile by updating imports/bench
names accordingly so no dead/unused symbols remain (targets: matchesID,
matchesIncludeID, BenchmarkFilterMatches_Mixed_Old).
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2cbfa84b-3c36-403b-98e9-4ae6fbd6a5fd

📥 Commits

Reviewing files that changed from the base of the PR and between 56e53cf and 643a64c.

📒 Files selected for processing (3)
  • pkg/catalog/index/filter.go
  • pkg/catalog/index/filter_bench_test.go
  • pkg/catalog/index/filter_test.go

Comment thread pkg/catalog/index/filter_bench_test.go Outdated
Comment thread pkg/catalog/index/filter.go Outdated
Comment thread pkg/catalog/index/filter.go
Comment thread pkg/catalog/index/filter.go Outdated
… modifying filter was always not-thread safe
@neo-by-projectdiscovery-dev

neo-by-projectdiscovery-dev Bot commented Apr 13, 2026

Copy link
Copy Markdown

Neo - PR Security Review

Caution

Neo couldn't finish analyzing this pull request during this run. Please run the review again.

Comment @pdneo help for available commands. · Open in Neo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/catalog/index/filter.go (1)

187-202: Address the TODO before merging.

The comment explicitly states "Remove before PR merged." If this function is only needed for benchmark comparison during review, consider either:

  1. Removing it now along with the *_Old benchmark variant
  2. If keeping the old benchmark for historical comparison, update the comment to reflect the actual intent (e.g., "Retained for benchmark comparison")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/index/filter.go` around lines 187 - 202, The matchesID function
is flagged for removal but still present; either remove matchesID and any
associated *_Old benchmark variants (so no deprecated helpers remain), or if you
intentionally keep it for benchmark comparison, update the TODO/comment to a
clear retention note (e.g., "Retained for benchmark comparison") and mark it
with Deprecated and reason; locate the matchesID function and any *_Old
benchmark names in the repo and apply the chosen change consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/catalog/index/filter.go`:
- Around line 187-202: The matchesID function is flagged for removal but still
present; either remove matchesID and any associated *_Old benchmark variants (so
no deprecated helpers remain), or if you intentionally keep it for benchmark
comparison, update the TODO/comment to a clear retention note (e.g., "Retained
for benchmark comparison") and mark it with Deprecated and reason; locate the
matchesID function and any *_Old benchmark names in the repo and apply the
chosen change consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e5014b7b-0c50-49b0-a625-f187ee2ad91f

📥 Commits

Reviewing files that changed from the base of the PR and between 643a64c and ad91d5d.

📒 Files selected for processing (1)
  • pkg/catalog/index/filter.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/catalog/index/filter_bench_test.go (1)

39-46: Deduplicate benchmark case tables to avoid drift.

The same cases are declared twice. Extracting them once will prevent future divergence between old/new benchmark suites.

♻️ Suggested refactor
+var benchmarkCases = []struct{ exact, wildcards int }{
+	{10, 0},
+	{100, 0},
+	{1000, 0},
+	{100, 1},
+	{100, 3},
+	{100, 5},
+}
+
 func BenchmarkFilterMatches(b *testing.B) {
 	corpus := makeMetadataCorpus(templateCount)
-
-	cases := []struct{ exact, wildcards int }{
-		{10, 0},
-		{100, 0},
-		{1000, 0},
-		{100, 1},
-		{100, 3},
-		{100, 5},
-	}
-
-	for _, tc := range cases {
+	for _, tc := range benchmarkCases {
 		b.Run(fmt.Sprintf("ids=%d,patterns=%d", tc.exact, tc.wildcards), func(b *testing.B) {
 			...
 		})
 	}
 }
 
 func BenchmarkFilterMatches_Old(b *testing.B) {
 	corpus := makeMetadataCorpus(templateCount)
-
-	cases := []struct{ exact, wildcards int }{
-		{10, 0},
-		{100, 0},
-		{1000, 0},
-		{100, 1},
-		{100, 3},
-		{100, 5},
-	}
-
-	for _, tc := range cases {
+	for _, tc := range benchmarkCases {
 		b.Run(fmt.Sprintf("ids=%d,patterns=%d", tc.exact, tc.wildcards), func(b *testing.B) {
 			...
 		})
 	}
 }

Also applies to: 66-73

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/index/filter_bench_test.go` around lines 39 - 46, The benchmark
table "cases" is duplicated; consolidate it into a single shared declaration and
reuse it in both places to avoid drift. Replace the two inline slices with one
extracted variable (e.g., var cases = []struct{ exact, wildcards int }{...})
placed at the top of the test or package scope, and update both benchmark usages
to reference that single "cases" variable so both suites use the same data.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/catalog/index/filter_bench_test.go`:
- Around line 39-46: The benchmark table "cases" is duplicated; consolidate it
into a single shared declaration and reuse it in both places to avoid drift.
Replace the two inline slices with one extracted variable (e.g., var cases =
[]struct{ exact, wildcards int }{...}) placed at the top of the test or package
scope, and update both benchmark usages to reference that single "cases"
variable so both suites use the same data.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29d4b527-e289-4dca-856a-265a5b1166e2

📥 Commits

Reviewing files that changed from the base of the PR and between ad91d5d and ec5f650.

📒 Files selected for processing (1)
  • pkg/catalog/index/filter_bench_test.go

@dwisiswant0 dwisiswant0 changed the title refactor: Improve catalog filter efficiency by splitting exact matches & pattern perf(catalog): split exact matches & pattern Apr 14, 2026
@dwisiswant0
dwisiswant0 self-requested a review April 14, 2026 22:59
@Mzack9999

Copy link
Copy Markdown
Member

@CodeRabbit ai create an issue for this PR

@coderabbitai

coderabbitai Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@Mzack9999, I've created a GitHub issue for PR #7340. Here's a summary of what was included in the issue:

  • Title: refactor: Improve catalog filter efficiency by splitting exact matches & pattern
  • Body: Describes the O(N×M) performance problem with the current (*Filter).Matches implementation, the proposed solution (splitting IDs into exact-match maps vs. wildcard pattern slices via a new Compile() method), benchmark results showing up to ~3,585× speedup, and links back to PR #7340.

🏁 Script executed:

gh issue create \
  --repo projectdiscovery/nuclei \
  --title "refactor: Improve catalog filter efficiency by splitting exact matches & pattern" \
  --body "## Overview

This issue tracks the work introduced in PR `#7340` to improve the efficiency of catalog ID filtering in Nuclei.

## Problem

The existing implementation in \`(*Filter).Matches\` checks each template (N) against all included IDs (M), resulting in **O(N×M) complexity**. Treating every ID as a glob pattern (via \`filepath.Match\`) is CPU-expensive when there are many exact IDs, as seen in the pprof flame graph where \`index.(*Filter).matchesIncludes\` → \`filepath.Match\` → \`filepath.matchChunk\` dominates CPU time.

## Proposed Solution

- Split \`IDs\` and \`ExcludeIDs\` into two categories at compile time:
  - **Exact matches**: stored in a \`map[string]struct{}\` for O(1) lookup.
  - **Pattern matches**: IDs containing wildcard characters (\`*\`, \`?\`, \`[\`) kept as slices for \`filepath.Match\` evaluation.
- Introduce \`(*Filter).Compile()\` (guarded by \`sync.Once\`) to pre-process the filter on first use.
- Replace \`matchesID\` iterations with new \`matchesIncludeID\` / \`matchesExcludeID\` methods.

## Benchmark Results

| Scenario | New (ns/op) | Old (ns/op) | Speedup |
|---|---|---|---|
| ids=1000, patterns=0 | 245,167 | 879,078,188 | ~3,585× |
| Mixed ids/patterns | Significant improvement across all cases | | |

## Files Changed

- \`pkg/catalog/index/filter.go\` — core refactor (+88/-13 lines)
- \`pkg/catalog/index/filter_bench_test.go\` — new benchmark file (+94 lines)
- \`pkg/catalog/index/filter_test.go\` — updated tests (+7/-4 lines)

## References

- PR: `#7340`
- Requested by: `@Mzack9999`"

Length of output: 55


@Mzack9999, the issue has been created successfully! You can view it here:

👉 #7367

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
pkg/catalog/index/filter.go (1)

187-190: ⚠️ Potential issue | 🟠 Major

Document Filter as immutable once compiled/in use.

The current comment still suggests mutating IDs/ExcludeIDs and rerunning Compile(), but that is unsafe once Matches() may be running concurrently against the cached maps/pattern slices. Please document the safe contract instead: call Compile() before sharing if you want eager initialization, and treat the filter as immutable after the first Compile()/Matches().

Suggested doc fix
 // Compile pre-processes IDs and ExcludeIDs into fast lookup structures.
 // The first time Matches is called, this is called automatically.
-// If IDs or ExcludeIDs are modified after calling Matches, this must be called manually.
-// This method is not thread-safe, so make sure noone is using the filter when calling it.
+// Call Compile before sharing the filter if you want eager initialization.
+// After Compile or the first Matches call, treat IDs and ExcludeIDs as immutable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/catalog/index/filter.go` around lines 187 - 190, Update the comment for
Filter to state that once Compile() or Matches() has been called (which
initializes internal lookup maps/slices), the Filter must be treated as
immutable and must not be mutated (do not change IDs or ExcludeIDs) while
Matches() may be called concurrently; also advise callers to call Compile()
before sharing the Filter for concurrent use if they want eager initialization
rather than relying on the first Matches() to lazily compile.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@pkg/catalog/index/filter.go`:
- Around line 187-190: Update the comment for Filter to state that once
Compile() or Matches() has been called (which initializes internal lookup
maps/slices), the Filter must be treated as immutable and must not be mutated
(do not change IDs or ExcludeIDs) while Matches() may be called concurrently;
also advise callers to call Compile() before sharing the Filter for concurrent
use if they want eager initialization rather than relying on the first Matches()
to lazily compile.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a735dfb7-0fc9-4ce6-bccf-1d9a3f91ec2d

📥 Commits

Reviewing files that changed from the base of the PR and between ec5f650 and 86cc092.

📒 Files selected for processing (2)
  • pkg/catalog/index/filter.go
  • pkg/catalog/index/filter_bench_test.go

@Mzack9999
Mzack9999 merged commit a3c07e3 into projectdiscovery:dev Apr 29, 2026
20 checks passed
@mikhail5555
mikhail5555 deleted the feature/improved-filter-performance branch April 30, 2026 07:50
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.

refactor: Improve catalog filter efficiency by splitting exact matches & pattern

2 participants