[red-knot] make large-union benchmark slow again (#17418)

## Summary

Now that we've made the large-unions benchmark fast, let's make it slow
again!

This adds a following operation (checking `len`) on the large union,
which is slow, even though building the large union is now fast. (This
is also observed in a real-world code sample.) It's slow because for
every element of the union, we fetch its `__len__` method and check it
for compatibility with `Sized`.

We can make this fast by extending the grouped-types approach, as
discussed in https://github.com/astral-sh/ruff/pull/17403, so that we
can do this `__len__` operation (which is identical for every literal
string) just once for all literal strings, instead of once per literal
string type in the union.

Until we do that, we can make this acceptably fast again for now by
setting a lowish limit on union size, which we can increase in the
future when we make it fast. This is what I'll do in the next PR.

## Test Plan

`cargo bench --bench red_knot`
This commit is contained in:
Carl Meyer 2025-04-16 07:05:42 -07:00 committed by GitHub
parent a1f361949e
commit 5a115e750d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -260,10 +260,14 @@ fn benchmark_many_string_assignments(criterion: &mut Criterion) {
criterion.bench_function("red_knot_micro[many_string_assignments]", |b| {
b.iter_batched_ref(
|| {
// This is a micro benchmark, but it is effectively identical to a code sample
// observed "in the wild":
setup_micro_case(
r#"
def f(x) -> str:
s = ""
# Each conditional doubles the size of the union of string literal types,
# so if we go up to attr10, we have 2**10 = 1024 string literal types
if x.attr1:
s += "attr1"
if x.attr2:
@ -284,8 +288,11 @@ fn benchmark_many_string_assignments(criterion: &mut Criterion) {
s += "attr9"
if x.attr10:
s += "attr10"
if x.attr11:
s += "attr11"
# The above checked how fast we are in building the union; this checks how
# we manage it once it is built. If implemented naively, this has to check
# each member of the union for compatibility with the Sized protocol.
if len(s) > 0:
s = s[:-3]
return s
"#,
)