Thread (10 messages) 10 messages, 5 authors, 4d ago

Re: [PATCH] branch: avoid slow strvec Coccinelle matching

From: Junio C Hamano <hidden>
Date: 2026-07-24 15:27:09

tnyman@openai.com writes:
From: Ted Nyman <redacted>

The --delete-merged implementation declares a loop index at function
scope and reuses it to walk its strvec of upstreams and its list of
candidate branches. Coccinelle 1.1.1 spends hours matching this against
the separate_loop_index rule in tools/coccinelle/strvec.cocci, causing
the static-analysis job on 'seen' to reach its six-hour timeout.
...
The CI failure reproduces locally with Coccinelle 1.1.1: applying
strvec.cocci to the original builtin/branch.c still times out with
"spatch --timeout 120". With this change, the same check completes in
0.06 seconds.
Impressive.  Nicely analyzed.

Even though this is very much like bending the code only to appease
the checker, the resulting code is arguably better in this
particular case, so I do not feel as bad as I have on other
occasions when we had to work around deficiencies in our tools [*].

I see Harald already took this in the latest update.  Thanks for
working well together.

[*]

 * Here, I do not blame Coccinelle alone.  The performance bug is
   caused by a combination of Coccinelle and the 'strvec' check that
   makes it so inefficient.  I wonder if there are ways to make the
   checks in 'strvec.cocci' more efficient?

quoted hunk ↗ jump to hunk
diff --git a/builtin/branch.c b/builtin/branch.c
index 42f2221547..2415a275ea 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -797,10 +797,9 @@ static int delete_merged_branches(const struct strvec *upstreams,
 	struct strbuf key = STRBUF_INIT;
 	struct hashmap_iter iter;
 	struct strmap_entry *entry;
-	size_t i;
 	int ret = 0;
 
-	for (i = 0; i < upstreams->nr; i++)
+	for (size_t i = 0; i < upstreams->nr; i++)
 		if (ref_filter_forked_add(&filter, upstreams->v[i]) < 0)
 			die(_("'%s' is not a valid branch or pattern"),
 			    upstreams->v[i]);
@@ -809,7 +808,7 @@ static int delete_merged_branches(const struct strvec *upstreams,
 	filter.name_patterns = argv;
 	filter_refs(&candidates, &filter, filter.kind);
 
-	for (i = 0; i < (size_t)candidates.nr; i++) {
+	for (size_t i = 0; i < (size_t)candidates.nr; i++) {
 		const char *branch_refname = candidates.items[i]->refname;
 		const char *branch_name;
 		struct branch *branch;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help