public inbox for git@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] builtin/help.c: move strbuf out of help loops
@ 2026-03-10  7:03 Siddharth Shrimali
  2026-03-10 12:41 ` Patrick Steinhardt
  0 siblings, 1 reply; 7+ messages in thread
From: Siddharth Shrimali @ 2026-03-10  7:03 UTC (permalink / raw)
  To: git; +Cc: gitster, ps, jonatan, r.siddharth.shrimali

In list_config_help(), a strbuf was being initialized and released
inside two separate loops. This caused unnecessary memory allocation
and deallocation on every iteration.

Move the strbuf declaration to the top of the function and use
strbuf_reset() inside the loops to reuse the same buffer. Similarly
release() the buffer at the end of the function to free the memory.
This improves performance by avoiding repeated heap pressure by reducing
the number of allocations.

This also fixes a minor memory leak when the SHOW_CONFIG_HUMAN case
triggers a continue.

Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
---
 builtin/help.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/builtin/help.c b/builtin/help.c
index 86a3d03a9b..07398b430e 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -134,10 +134,10 @@ static void list_config_help(enum show_config_type type)
 	struct string_list keys = STRING_LIST_INIT_DUP;
 	struct string_list keys_uniq = STRING_LIST_INIT_DUP;
 	struct string_list_item *item;
+	struct strbuf sb = STRBUF_INIT;
 
 	for (p = config_name_list; *p; p++) {
 		const char *var = *p;
-		struct strbuf sb = STRBUF_INIT;
 
 		for (e = slot_expansions; e->prefix; e++) {
 
@@ -149,7 +149,6 @@ static void list_config_help(enum show_config_type type)
 				break;
 			}
 		}
-		strbuf_release(&sb);
 		if (!e->prefix)
 			string_list_append(&keys, var);
 	}
@@ -161,10 +160,10 @@ static void list_config_help(enum show_config_type type)
 
 	string_list_sort(&keys);
 	for (size_t i = 0; i < keys.nr; i++) {
+		strbuf_reset(&sb);
 		const char *var = keys.items[i].string;
 		const char *wildcard, *tag, *cut;
 		const char *dot = NULL;
-		struct strbuf sb = STRBUF_INIT;
 
 		switch (type) {
 		case SHOW_CONFIG_HUMAN:
@@ -195,13 +194,13 @@ static void list_config_help(enum show_config_type type)
 
 		strbuf_add(&sb, var, cut - var);
 		string_list_append(&keys_uniq, sb.buf);
-		strbuf_release(&sb);
 
 	}
 	string_list_clear(&keys, 0);
 	string_list_remove_duplicates(&keys_uniq, 0);
 	for_each_string_list_item(item, &keys_uniq)
 		puts(item->string);
+	strbuf_release(&sb);
 	string_list_clear(&keys_uniq, 0);
 }
 
-- 
2.51.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] builtin/help.c: move strbuf out of help loops
  2026-03-10  7:03 [PATCH] builtin/help.c: move strbuf out of help loops Siddharth Shrimali
@ 2026-03-10 12:41 ` Patrick Steinhardt
  2026-03-10 16:00   ` [PATCH v2] " Siddharth Shrimali
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick Steinhardt @ 2026-03-10 12:41 UTC (permalink / raw)
  To: Siddharth Shrimali; +Cc: git, gitster, jonatan

On Tue, Mar 10, 2026 at 12:33:28PM +0530, Siddharth Shrimali wrote:
> In list_config_help(), a strbuf was being initialized and released
> inside two separate loops. This caused unnecessary memory allocation
> and deallocation on every iteration.
> 
> Move the strbuf declaration to the top of the function and use
> strbuf_reset() inside the loops to reuse the same buffer. Similarly
> release() the buffer at the end of the function to free the memory.
> This improves performance by avoiding repeated heap pressure by reducing
> the number of allocations.
> 
> This also fixes a minor memory leak when the SHOW_CONFIG_HUMAN case
> triggers a continue.
> 
> Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
> ---
>  builtin/help.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/builtin/help.c b/builtin/help.c
> index 86a3d03a9b..07398b430e 100644
> --- a/builtin/help.c
> +++ b/builtin/help.c
> @@ -134,10 +134,10 @@ static void list_config_help(enum show_config_type type)
>  	struct string_list keys = STRING_LIST_INIT_DUP;
>  	struct string_list keys_uniq = STRING_LIST_INIT_DUP;
>  	struct string_list_item *item;
> +	struct strbuf sb = STRBUF_INIT;
>  
>  	for (p = config_name_list; *p; p++) {
>  		const char *var = *p;
> -		struct strbuf sb = STRBUF_INIT;
>  
>  		for (e = slot_expansions; e->prefix; e++) {
>  

What's missing from the context here is that the next line already knows
to `strbuf_reset()`. You could do a trick and drop the empty newline
here while at it, as that would then make the reset call visible.

> @@ -149,7 +149,6 @@ static void list_config_help(enum show_config_type type)
>  				break;
>  			}
>  		}
> -		strbuf_release(&sb);
>  		if (!e->prefix)
>  			string_list_append(&keys, var);
>  	}
> @@ -161,10 +160,10 @@ static void list_config_help(enum show_config_type type)
>  
>  	string_list_sort(&keys);
>  	for (size_t i = 0; i < keys.nr; i++) {
> +		strbuf_reset(&sb);

Our coding style says that statements should come after variable
declarations.

Other than that this patch looks good to me, thanks!

Patrick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2] builtin/help.c: move strbuf out of help loops
  2026-03-10 12:41 ` Patrick Steinhardt
@ 2026-03-10 16:00   ` Siddharth Shrimali
  2026-03-10 20:33     ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Siddharth Shrimali @ 2026-03-10 16:00 UTC (permalink / raw)
  To: git; +Cc: ps, gitster, jonatan, r.siddharth.shrimali

In list_config_help(), a strbuf was being initialized and released
inside two separate loops. This caused unnecessary memory allocation
and deallocation on every iteration.

Move the strbuf declaration to the top of the function and use
strbuf_reset() inside the loops to reuse the same buffer. Similarly
release() the buffer at the end of the function to free the memory.
This improves performance by avoiding repeated heap pressure by reducing
the number of allocations.

This also fixes a minor memory leak when the SHOW_CONFIG_HUMAN case
triggers a continue.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Siddharth Shrimali <r.siddharth.shrimali@gmail.com>
---
Changes in v2:
- Moved strbuf_reset() after variable declarations to follow 
  coding standards.
- Removed unnecessary empty lines to tighten the code as suggested 
  by Patrick.

 builtin/help.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/builtin/help.c b/builtin/help.c
index 86a3d03a9b..467a0763a6 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -134,13 +134,11 @@ static void list_config_help(enum show_config_type type)
 	struct string_list keys = STRING_LIST_INIT_DUP;
 	struct string_list keys_uniq = STRING_LIST_INIT_DUP;
 	struct string_list_item *item;
+	struct strbuf sb = STRBUF_INIT;
 
 	for (p = config_name_list; *p; p++) {
 		const char *var = *p;
-		struct strbuf sb = STRBUF_INIT;
-
 		for (e = slot_expansions; e->prefix; e++) {
-
 			strbuf_reset(&sb);
 			strbuf_addf(&sb, "%s.%s", e->prefix, e->placeholder);
 			if (!strcasecmp(var, sb.buf)) {
@@ -149,7 +147,6 @@ static void list_config_help(enum show_config_type type)
 				break;
 			}
 		}
-		strbuf_release(&sb);
 		if (!e->prefix)
 			string_list_append(&keys, var);
 	}
@@ -164,7 +161,7 @@ static void list_config_help(enum show_config_type type)
 		const char *var = keys.items[i].string;
 		const char *wildcard, *tag, *cut;
 		const char *dot = NULL;
-		struct strbuf sb = STRBUF_INIT;
+		strbuf_reset(&sb);
 
 		switch (type) {
 		case SHOW_CONFIG_HUMAN:
@@ -195,13 +192,13 @@ static void list_config_help(enum show_config_type type)
 
 		strbuf_add(&sb, var, cut - var);
 		string_list_append(&keys_uniq, sb.buf);
-		strbuf_release(&sb);
 
 	}
 	string_list_clear(&keys, 0);
 	string_list_remove_duplicates(&keys_uniq, 0);
 	for_each_string_list_item(item, &keys_uniq)
 		puts(item->string);
+	strbuf_release(&sb);
 	string_list_clear(&keys_uniq, 0);
 }
 
-- 
2.51.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] builtin/help.c: move strbuf out of help loops
  2026-03-10 16:00   ` [PATCH v2] " Siddharth Shrimali
@ 2026-03-10 20:33     ` Junio C Hamano
  2026-03-11 18:13       ` Siddharth Shrimali
  0 siblings, 1 reply; 7+ messages in thread
From: Junio C Hamano @ 2026-03-10 20:33 UTC (permalink / raw)
  To: Siddharth Shrimali; +Cc: git, ps, jonatan

Siddharth Shrimali <r.siddharth.shrimali@gmail.com> writes:

> In list_config_help(), a strbuf was being initialized and released
> inside two separate loops. This caused unnecessary memory allocation
> and deallocation on every iteration.

OK.  strbuf_init() followed by a loop that does strbuf_reset()
followed by use of strbuf, concluded with strbuf_release() after
leaving the loop, is a fairly common pattern to optimize such a use
pattern.

> This also fixes a minor memory leak when the SHOW_CONFIG_HUMAN case
> triggers a continue.

Does it?  You are essentially saying that

	for (int i = 0; i < 10; i++) {
		struct strbuf sb = STRBUF_INIT;
 
		switch (SHOW_CONFIG_HUMAN) {
                case SHOW_CONFIG_HUMAN:
			continue;
		}
	}

leaks, but a strbuf merely initialized can safely be discarded
without leaking any resources, can't it?

> diff --git a/builtin/help.c b/builtin/help.c
> index 86a3d03a9b..467a0763a6 100644
> --- a/builtin/help.c
> +++ b/builtin/help.c
> @@ -134,13 +134,11 @@ static void list_config_help(enum show_config_type type)
>  	struct string_list keys = STRING_LIST_INIT_DUP;
>  	struct string_list keys_uniq = STRING_LIST_INIT_DUP;
>  	struct string_list_item *item;
> +	struct strbuf sb = STRBUF_INIT;
>  
>  	for (p = config_name_list; *p; p++) {
>  		const char *var = *p;
> -		struct strbuf sb = STRBUF_INIT;
> -

A blank between the variable declaration block and the first
statement makes the code easier to follow.  Loss of a blank line
here is of dubious value.

>  		for (e = slot_expansions; e->prefix; e++) {
> -

This removal is good.

>  			strbuf_reset(&sb);

So we first reset, and then start building things in sb.

>  			strbuf_addf(&sb, "%s.%s", e->prefix, e->placeholder);
>  			if (!strcasecmp(var, sb.buf)) {
> @@ -149,7 +147,6 @@ static void list_config_help(enum show_config_type type)
>  				break;
>  			}
>  		}
> -		strbuf_release(&sb);
>  		if (!e->prefix)
>  			string_list_append(&keys, var);

We no longer have to release it inside the loop, as we will reset at
the beginning of the next iteration.

>  	}
> @@ -164,7 +161,7 @@ static void list_config_help(enum show_config_type type)
>  		const char *var = keys.items[i].string;
>  		const char *wildcard, *tag, *cut;
>  		const char *dot = NULL;
> -		struct strbuf sb = STRBUF_INIT;
> +		strbuf_reset(&sb);
>  

The arrangement of the blank line is wrong here.  The original was
the last line of a declaration block which should come before the
blank.  Now you are removing it, and then adding a strbuf_reset() as
the first statement, which should come after the blank that delimits
the declarations and statements.

In any case, here we have a second loop that wants to use a scratch
strbuf, so again we reset it at the beginning of the loop before we
use it.

>  		switch (type) {
>  		case SHOW_CONFIG_HUMAN:
> @@ -195,13 +192,13 @@ static void list_config_help(enum show_config_type type)
>  
>  		strbuf_add(&sb, var, cut - var);
>  		string_list_append(&keys_uniq, sb.buf);
> -		strbuf_release(&sb);
>  

And we no longer release it during iteration.  Instead ...


>  	}
>  	string_list_clear(&keys, 0);
>  	string_list_remove_duplicates(&keys_uniq, 0);
>  	for_each_string_list_item(item, &keys_uniq)
>  		puts(item->string);
> +	strbuf_release(&sb);

... we release after we leave the loop.

>  	string_list_clear(&keys_uniq, 0);
>  }


Having looked at this patch, I recall somebody else is revamping
this function already, so this patch would step on their toes.
Please pay attention to what is going on in the project around the
code you are touching, and coordinate with others who are working on
the same code if necessary.

https://lore.kernel.org/git/20260228104654.80831-2-amishhhaaaa@gmail.com/

Thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] builtin/help.c: move strbuf out of help loops
  2026-03-10 20:33     ` Junio C Hamano
@ 2026-03-11 18:13       ` Siddharth Shrimali
  2026-03-11 19:30         ` Amisha Chhajed
  0 siblings, 1 reply; 7+ messages in thread
From: Siddharth Shrimali @ 2026-03-11 18:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, ps, jonatan, Amisha Chhajed

On Wed, 11 Mar 2026 at 02:03, Junio C Hamano <gitster@pobox.com> wrote:
> Having looked at this patch, I recall somebody else is revamping
> this function already, so this patch would step on their toes.
> Please pay attention to what is going on in the project around the
> code you are touching, and coordinate with others who are working on
> the same code if necessary.
>
> https://lore.kernel.org/git/20260228104654.80831-2-amishhhaaaa@gmail.com/
>
> Thanks.

Hi Junio (CC'ing Amisha),

After looking at the refactor of list_config_help() in the
other active thread, I agree that my optimization is no longer
necessary.

Amisha's new structure with set_config_vars() and set_config_sections()
is much cleaner. Since the logic is now encapsulated in these helpers,
my proposed changes would not be applicable.

I'll drop this patch and focus on my other contributions.
Thanks for the guidance!

Regards,
Siddharth

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] builtin/help.c: move strbuf out of help loops
  2026-03-11 18:13       ` Siddharth Shrimali
@ 2026-03-11 19:30         ` Amisha Chhajed
  2026-03-11 19:48           ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Amisha Chhajed @ 2026-03-11 19:30 UTC (permalink / raw)
  To: Siddharth Shrimali; +Cc: Junio C Hamano, git, ps, jonatan

> After looking at the refactor of list_config_help() in the
> other active thread, I agree that my optimization is no longer
> necessary.
>
> Amisha's new structure with set_config_vars() and set_config_sections()
> is much cleaner. Since the logic is now encapsulated in these helpers,
> my proposed changes would not be applicable.

I feel removing out the strbuf initialisation and release out of the
loop is still applicable,
I have added all the parts in v5 which were not fixed by my
improvements and tagged you,
check it out here
https://lore.kernel.org/git/20260311192151.60489-1-amishhhaaaa@gmail.com/

-- 
Thanks,
Amisha

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] builtin/help.c: move strbuf out of help loops
  2026-03-11 19:30         ` Amisha Chhajed
@ 2026-03-11 19:48           ` Junio C Hamano
  0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2026-03-11 19:48 UTC (permalink / raw)
  To: Amisha Chhajed; +Cc: Siddharth Shrimali, git, ps, jonatan

Amisha Chhajed <amishhhaaaa@gmail.com> writes:

>> After looking at the refactor of list_config_help() in the
>> other active thread, I agree that my optimization is no longer
>> necessary.
>>
>> Amisha's new structure with set_config_vars() and set_config_sections()
>> is much cleaner. Since the logic is now encapsulated in these helpers,
>> my proposed changes would not be applicable.
>
> I feel removing out the strbuf initialisation and release out of the
> loop is still applicable,
> I have added all the parts in v5 which were not fixed by my
> improvements and tagged you,
> check it out here
> https://lore.kernel.org/git/20260311192151.60489-1-amishhhaaaa@gmail.com/

I love seeing two community members, both of which are relatively
newcomers, working well together ;-).

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-03-11 19:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10  7:03 [PATCH] builtin/help.c: move strbuf out of help loops Siddharth Shrimali
2026-03-10 12:41 ` Patrick Steinhardt
2026-03-10 16:00   ` [PATCH v2] " Siddharth Shrimali
2026-03-10 20:33     ` Junio C Hamano
2026-03-11 18:13       ` Siddharth Shrimali
2026-03-11 19:30         ` Amisha Chhajed
2026-03-11 19:48           ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox