test: replace flaky StringMatcher.Memory with deterministic sizeof static_asserts#44699
Closed
test: replace flaky StringMatcher.Memory with deterministic sizeof static_asserts#44699
Conversation
Member
|
cc @adisuissa |
…asserts Remove the tcmalloc-consumedBytes-based TEST_F(StringMatcher, Memory) which was producing ~5/1000 flakes on gcc CI (page-level allocation jitter, hard-coded constants needing manual updates on every dep bump). Replace with: - Compile-time static_asserts on sizeof(ExactStringMatcher), PrefixStringMatcher, SuffixStringMatcher, ContainsStringMatcher, RegexStringMatcher, CustomStringMatcher, and StringMatcherImpl, expressed in terms of sizeof(std::string) + sizeof(void*) so they are portable across libc++/libstdc++ and 32-/64-bit builds. These fire deterministically at compile time if someone adds an unused field to any variant alternative. - A runtime TEST_F(StringMatcher, SizeIsBounded) that mirrors the static_asserts so the bounds are visible in test-runner output. - A comment block explaining why the old test was removed and what structural property the new assertions enforce, pointing back to PR #37782. Agent-Logs-Url: https://github.com/envoyproxy/envoy/sessions/6c75cfb3-7651-4bd2-9682-cb5b74325ac0 Co-authored-by: phlax <454682+phlax@users.noreply.github.com>
…tcherImpl bound Agent-Logs-Url: https://github.com/envoyproxy/envoy/sessions/6c75cfb3-7651-4bd2-9682-cb5b74325ac0 Co-authored-by: phlax <454682+phlax@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix broken memory regression test for StringMatcher
test: replace flaky StringMatcher.Memory with deterministic sizeof static_asserts
Apr 28, 2026
Member
|
moved to #44701 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
StringMatcher.Memorywas asserting tcmalloc page-level heap consumption against hard-coded byte ceilings (530176 + 5*8192,15603776 + 10*8192). These constants are sensitive to size-class bucketing, span layout, and prior heap state — producing ~5/1000 flakes on gcc CI and requiring manual re-tuning on every tcmalloc/abseil/protobuf bump (PRs #37782, #43467). Simultaneously too tight (flakes on allocator noise) and too loose (can't detect small genuine regressions within the slack).Changes
Removed
TEST_F(StringMatcher, Memory)and allEXPECT_MEMORY_LE/Memory::TestUtil::MemoryTestusage.Added compile-time
static_asserts that enforce the structural invariant PR string-matcher: reduce per-matcher memory #37782 actually cared about — that each variant alternative carries only its required data andStringMatcherImpldoesn't retain the proto:Bounds use
sizeof(std::string)andsizeof(void*)rather than raw byte counts, making them portable across libc++ (sizeof(std::string)==24) and libstdc++ (sizeof(std::string)==32).Added
TEST_F(StringMatcher, SizeIsBounded)mirroring the static_asserts at runtime for test-runner visibility, with a comment block documenting the removed test's failure mode and the design intent.No BUILD changes needed —
memory_test_utility_libwas never an explicit dep ofmatchers_test.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
dl.google.com/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)/home/REDACTED/.cache/envoy-bazel/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/home/REDACTED/.cache/envoy-bazel/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/home/REDACTED/.cache/envoy-bazel/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/home/REDACTED/.cache/envoy-bazel/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/home/REDACTED/. 1/x64/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin/node(dns block)ftpmirror.gnu.org/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)mirror.bazel.build/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)pkgconfig.freedesktop.org/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/bin/java bazel(envoy) --add-opens=java.base/java.lang=ALL-UNNAMED -Xverify:none -Djava.util.logging.config.file=/build/bazel_root/base/javalog.properties -Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier -XX:-MaxFDLimit -Djava.library.path=/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/embedded_tools/jdk/lib/server:/build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/ -Dfile.encoding=ISO-8859-1 -Duser.country= -Duser.language= -Duser.variant= -Xmx3g -DBAZEL_TRACK_SOURCE_DIRECTORIES=1 -Djavax.net.ssl.trustStore=/tmp/custom-cacerts -Djavax.net.ssl.trustStorePassword=changeit -jar /build/bazel_root/install/fb2a7f6d344d2f4e335882534df59296/A-server.jar --max_idle_secs=10800 --noshutdown_on_low_sys_mem --connect_timeout_secs=30(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
Background
TEST_F(StringMatcher, Memory)intest/common/common/matchers_test.ccwas added in PR #37782 to guard against per-matcher memory regressions inStringMatcherImpl(thestd::variant-based redesign).It asserts that the tcmalloc-reported
consumedBytes()after constructing 1000 matchers stays under a hard-coded ceiling (530176 + 5 * 8192for prefix,15603776 + 10 * 8192for regex).This test is fundamentally broken and is the source of recurring gcc CI flakes (~5/1000 reproduction rate, observed continuously on
mainsince at least the start of the current dev cycle). Specifically:StringMatcherImpl.15038016→15603776).+ N * 8192slack is an explicit acknowledgement that the signal has page-sized noise — so the test is simultaneously too tight (flakes on allocator noise) and too loose (won't detect a small genuine regression of, say, +16 bytes/matcher × 1000 = 16 KiB, which fits inside the slack).ExactStringMatcherdoesn't carry an unused regex pointer;StringMatcherImpldoesn't keep a copy of the proto"), not "the heap is N bytes after 1000 constructions."The recent failure mode, for reference:
— i.e. only ~24 KiB over a ~16 MiB ceiling.
Goal
Remove the flaky
EXPECT_MEMORY_LE-based test and replace it with deterministic checks that actually enforce the structural property #37782 was supposed to guard. Do not just delete the test — the per-matcher-size invariant is real and worth testing; the implementation just needs to test it deterministically.What to do
In
source/common/common/matchers.hthe relevant types are:ExactStringMatcher— holdsstd::string exact_; bool ignore_case_;PrefixStringMatcher— holdsstd::string prefix_; bool ignore_case_;SuffixStringMatcher— holdsstd::string suffix_; bool ignore_case_;ContainsStringMatcher— holdsstd::string contents_; bool ignore_case_;RegexStringMatcher— holdsRegex::CompiledMatcherPtr regex_;CustomStringMatcher— holdsStringMatcherPtr custom_;StringMatcherImpl— wrapsabsl::variant<...>of the above, plus two vtable pointers (it inheritsValueMatcherandStringMatcher).The point of the redesign was that
sizeof(StringMatcherImpl)should be roughlysizeof(largest variant alternative) + variant discriminator + vtable pointers— and crucially, that no alternative carries fields it doesn't need (e.g.ExactStringMatchermust not hold aRegexMatcherpointer;StringMatcherImplmust not hold a copy of the original proto).Replacement test design
In
test/common/common/matchers_test.cc, delete the existingTEST_F(StringMatcher, Memory)and replace it with the following deterministic checks. Put them in a new test (or two) — pick whatever names fit local conventions, e.g.StringMatcher.SizeIsBoundedandStringMatcher.AllocationsScaleLinearly.1. Compile-time
static_assertsize boundsAdd
static_asserts — either inside an anonymous-namespace test inmatchers_test.cc, or directly insource/common/common/matchers.ccif that's preferred for visibility — that pin the size of each variant alternative and ofStringMatcherImplitself. Use generous-but-tight bounds expressed in terms ofsizeof(std::string),sizeof(void*), etc., not raw byte counts, so they are portable across libc++/libstdc++ and 32/64-bit. For example: