[collector] Nginx collector recompiles constant regex patterns on every collection
Is there an existing issue for this?
- I have searched the existing issues
Current Behavior
NginxCollectImpl.regexNginxStatusMatch() calls Pattern.compile() on three regexes every time it runs, even though all three are static final String constants.
The constants (NginxCollectImpl.java, lines 72-74):
private static final String REGEX_KEYS = "server\\s+(\\w+)\\s+(\\w+)\\s+(\\w+)";
private static final String REGEX_VALUES = "(\\d+) (\\d+) (\\d+)";
private static final String REGEX_SERVER = "(\\w+): (\\d+)";Compiled fresh on every call (lines 268, 275, 277), in a method reached from collect():
Pattern pattern = Pattern.compile(REGEX_SERVER);
Pattern pattern1 = Pattern.compile(REGEX_KEYS);
Pattern pattern2 = Pattern.compile(REGEX_VALUES);collect() runs once per collection interval for every Nginx monitor, so these three constant regexes are recompiled repeatedly for no reason.
Expected Behavior
Because the regex strings are compile-time constants, the compiled Pattern objects should be created once as static final Pattern fields and reused, instead of being recompiled on every collection cycle.
Steps To Reproduce
Open the file NginxCollectImpl.java in the module hertzbeat-collector/hertzbeat-collector-basic (folder: collect/nginx).
Look at lines 72-74. Three regular expressions are defined as fixed constants (static final String) — they never change: REGEX_KEYS = "server\s+(\w+)\s+(\w+)\s+(\w+)" REGEX_VALUES = "(\d+) (\d+) (\d+)" REGEX_SERVER = "(\w+): (\d+)"
Now look at the method regexNginxStatusMatch() (lines 268, 275, 277). Every time it runs, it calls Pattern.compile() again on those same three constant strings: Pattern pattern = Pattern.compile(REGEX_SERVER); Pattern pattern1 = Pattern.compile(REGEX_KEYS); Pattern pattern2 = Pattern.compile(REGEX_VALUES);
This method is called from collect(), which HertzBeat runs once per collection cycle for every Nginx monitor. So the same unchanging regexes get compiled over and over on every cycle, which is wasted work. Compiling a regex is relatively expensive, and here it can simply be done once.
Note: found by reading the source code, not from a runtime error or crash.
Environment
HertzBeat version(s):master branch (commit 307ef0d); also present in the latest release v1.9.0Debug logs
N/A — this is a code-level performance issue found by reading the source, so there is no runtime error or log to attach.
Anything else?
The fix is simple: move the three regexes into static final Pattern fields that are compiled once when the class loads, and reuse them, instead of calling Pattern.compile() on every collection cycle.
I measured the difference with a small benchmark (2,000,000 iterations on JDK 21):
recompile each call : 7,823 ms
compile once (fix) : 6,888 ms
speedup : ~1.1x fasterSo it's a small but measurable improvement, and a cleaner pattern overall. Happy to open a PR for it.
Source: apache/hertzbeat