From: "ZheNing Hu via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Jeff King" <peff@peff.net>, "Junio C Hamano" <gitster@pobox.com>,
"Christian Couder" <chriscool@tuxfamily.org>,
"Hariom Verma" <hariom18599@gmail.com>,
"Eric Sunshine" <sunshine@sunshineco.com>,
"Derrick Stolee" <stolee@gmail.com>,
"René Scharfe" <l.s.r@web.de>,
"ZheNing Hu" <adlternative@gmail.com>,
"ZheNing Hu" <adlternative@gmail.com>
Subject: [PATCH v2] [GSOC] ref-filter: use single strbuf for all output
Date: Wed, 07 Apr 2021 15:26:48 +0000 [thread overview]
Message-ID: <pull.927.v2.git.1617809209164.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.927.git.1617631280402.gitgitgadget@gmail.com>
From: ZheNing Hu <adlternative@gmail.com>
When we use `git for-each-ref`, every ref will call
`show_ref_array_item()` and allocate its own final strbuf
and error strbuf. Instead, we can reuse these two strbuf
for each step ref's output.
The performance for `git for-each-ref` on the Git repository
itself with performance testing tool `hyperfine` changes from
18.7 ms ± 0.4 ms to 18.2 ms ± 0.3 ms.
This approach is similar to the one used by 79ed0a5
(cat-file: use a single strbuf for all output, 2018-08-14)
to speed up the cat-file builtin.
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
---
[GSOC] ref-filter: use single strbuf for all output
Now git for-each-ref can reuse two buffers for all refs output, the
performance is slightly improved.
Now there may be a question : Should the original interface
show_ref_array_items be retained?
Thanks.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-927%2Fadlternative%2Fref-filter-single-buf-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-927/adlternative/ref-filter-single-buf-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/927
Range-diff vs v1:
1: bcc3feb4de7c ! 1: 3aed12c4f5a8 [GSOC] ref-filter: use single strbuf for all output
@@ Commit message
When we use `git for-each-ref`, every ref will call
`show_ref_array_item()` and allocate its own final strbuf
- and error strbuf. Instead, we can provide two single strbuf:
- final_buf and error_buf that get reused for each output.
+ and error strbuf. Instead, we can reuse these two strbuf
+ for each step ref's output.
- When run it 100 times:
+ The performance for `git for-each-ref` on the Git repository
+ itself with performance testing tool `hyperfine` changes from
+ 18.7 ms ± 0.4 ms to 18.2 ms ± 0.3 ms.
- $ git for-each-ref
-
- on git.git :
-
- 3.19s user
- 3.88s system
- 35% cpu
- 20.199 total
-
- to:
-
- 2.89s user
- 4.00s system
- 34% cpu
- 19.741 total
-
- The performance has been slightly improved.
+ This approach is similar to the one used by 79ed0a5
+ (cat-file: use a single strbuf for all output, 2018-08-14)
+ to speed up the cat-file builtin.
Signed-off-by: ZheNing Hu <adlternative@gmail.com>
## builtin/for-each-ref.c ##
-@@ builtin/for-each-ref.c: int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
- struct ref_array array;
- struct ref_filter filter;
- struct ref_format format = REF_FORMAT_INIT;
-+ struct strbuf final_buf = STRBUF_INIT;
-+ struct strbuf error_buf = STRBUF_INIT;
+@@ builtin/for-each-ref.c: static char const * const for_each_ref_usage[] = {
- struct option opts[] = {
- OPT_BIT('s', "shell", &format.quote_style,
+ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
+ {
+- int i;
+ struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
+ int maxcount = 0, icase = 0;
+ struct ref_array array;
@@ builtin/for-each-ref.c: int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
+
if (!maxcount || array.nr < maxcount)
maxcount = array.nr;
- for (i = 0; i < maxcount; i++)
+- for (i = 0; i < maxcount; i++)
- show_ref_array_item(array.items[i], &format);
-+ show_ref_array_item(array.items[i], &format, &final_buf, &error_buf);
++ show_ref_array_items(array.items, &format, maxcount);
ref_array_clear(&array);
return 0;
}
- ## builtin/tag.c ##
-@@ builtin/tag.c: static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
- struct ref_format *format)
- {
- struct ref_array array;
-+ struct strbuf final_buf = STRBUF_INIT;
-+ struct strbuf error_buf = STRBUF_INIT;
- char *to_free = NULL;
- int i;
-
-@@ builtin/tag.c: static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
- ref_array_sort(sorting, &array);
-
- for (i = 0; i < array.nr; i++)
-- show_ref_array_item(array.items[i], format);
-+ show_ref_array_item(array.items[i], format, &final_buf, &error_buf);
- ref_array_clear(&array);
- free(to_free);
-
-
## ref-filter.c ##
@@ ref-filter.c: int format_ref_array_item(struct ref_array_item *info,
+ return 0;
}
- void show_ref_array_item(struct ref_array_item *info,
-- const struct ref_format *format)
++void show_ref_array_items(struct ref_array_item **info,
+ const struct ref_format *format,
-+ struct strbuf *final_buf,
-+ struct strbuf *error_buf)
- {
-- struct strbuf final_buf = STRBUF_INIT;
-- struct strbuf error_buf = STRBUF_INIT;
-
-- if (format_ref_array_item(info, format, &final_buf, &error_buf))
-- die("%s", error_buf.buf);
-- fwrite(final_buf.buf, 1, final_buf.len, stdout);
-- strbuf_release(&error_buf);
-- strbuf_release(&final_buf);
-+ if (format_ref_array_item(info, format, final_buf, error_buf))
-+ die("%s", error_buf->buf);
-+ fwrite(final_buf->buf, 1, final_buf->len, stdout);
-+ strbuf_reset(error_buf);
-+ strbuf_reset(final_buf);
- putchar('\n');
- }
-
-@@ ref-filter.c: void pretty_print_ref(const char *name, const struct object_id *oid,
- const struct ref_format *format)
- {
- struct ref_array_item *ref_item;
++ size_t n)
++{
+ struct strbuf final_buf = STRBUF_INIT;
+ struct strbuf error_buf = STRBUF_INIT;
++ size_t i;
+
- ref_item = new_ref_array_item(name, oid);
- ref_item->kind = ref_kind_from_refname(name);
-- show_ref_array_item(ref_item, format);
-+ show_ref_array_item(ref_item, format, &final_buf, &error_buf);
- free_array_item(ref_item);
- }
-
++ for (i = 0; i < n; i++) {
++ if (format_ref_array_item(info[i], format, &final_buf, &error_buf))
++ die("%s", error_buf.buf);
++ fwrite(final_buf.buf, 1, final_buf.len, stdout);
++ strbuf_reset(&error_buf);
++ strbuf_reset(&final_buf);
++ putchar('\n');
++ }
++ strbuf_release(&error_buf);
++ strbuf_release(&final_buf);
++}
++
+ void show_ref_array_item(struct ref_array_item *info,
+ const struct ref_format *format)
+ {
## ref-filter.h ##
@@ ref-filter.h: int format_ref_array_item(struct ref_array_item *info,
- struct strbuf *final_buf,
struct strbuf *error_buf);
/* Print the ref using the given format and quote_style */
--void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format);
-+void show_ref_array_item(struct ref_array_item *info,
+ void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format);
++/* Print the refs using the given format and quote_style and maxcount */
++void show_ref_array_items(struct ref_array_item **info,
+ const struct ref_format *format,
-+ struct strbuf *final_buf,
-+ struct strbuf *error_buf);
++ size_t n);
++
/* Parse a single sort specifier and add it to the list */
void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *atom);
/* Callback function for parsing the sort option */
builtin/for-each-ref.c | 4 +---
ref-filter.c | 20 ++++++++++++++++++++
ref-filter.h | 5 +++++
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index cb9c81a04606..d630402230f3 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -16,7 +16,6 @@ static char const * const for_each_ref_usage[] = {
int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
{
- int i;
struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
int maxcount = 0, icase = 0;
struct ref_array array;
@@ -80,8 +79,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
if (!maxcount || array.nr < maxcount)
maxcount = array.nr;
- for (i = 0; i < maxcount; i++)
- show_ref_array_item(array.items[i], &format);
+ show_ref_array_items(array.items, &format, maxcount);
ref_array_clear(&array);
return 0;
}
diff --git a/ref-filter.c b/ref-filter.c
index f0bd32f71416..27bbf9b6c8ac 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2435,6 +2435,26 @@ int format_ref_array_item(struct ref_array_item *info,
return 0;
}
+void show_ref_array_items(struct ref_array_item **info,
+ const struct ref_format *format,
+ size_t n)
+{
+ struct strbuf final_buf = STRBUF_INIT;
+ struct strbuf error_buf = STRBUF_INIT;
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (format_ref_array_item(info[i], format, &final_buf, &error_buf))
+ die("%s", error_buf.buf);
+ fwrite(final_buf.buf, 1, final_buf.len, stdout);
+ strbuf_reset(&error_buf);
+ strbuf_reset(&final_buf);
+ putchar('\n');
+ }
+ strbuf_release(&error_buf);
+ strbuf_release(&final_buf);
+}
+
void show_ref_array_item(struct ref_array_item *info,
const struct ref_format *format)
{
diff --git a/ref-filter.h b/ref-filter.h
index 19ea4c413409..eb7e79a6676d 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -121,6 +121,11 @@ int format_ref_array_item(struct ref_array_item *info,
struct strbuf *error_buf);
/* Print the ref using the given format and quote_style */
void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format);
+/* Print the refs using the given format and quote_style and maxcount */
+void show_ref_array_items(struct ref_array_item **info,
+ const struct ref_format *format,
+ size_t n);
+
/* Parse a single sort specifier and add it to the list */
void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *atom);
/* Callback function for parsing the sort option */
base-commit: 2e36527f23b7f6ae15e6f21ac3b08bf3fed6ee48
--
gitgitgadget
next prev parent reply other threads:[~2021-04-07 15:26 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-05 14:01 [PATCH] [GSOC] ref-filter: use single strbuf for all output ZheNing Hu via GitGitGadget
2021-04-05 17:05 ` Eric Sunshine
2021-04-06 8:53 ` ZheNing Hu
2021-04-05 21:02 ` Derrick Stolee
2021-04-06 8:58 ` ZheNing Hu
2021-04-05 22:17 ` Jeff King
2021-04-06 9:49 ` ZheNing Hu
2021-04-06 10:35 ` ZheNing Hu
2021-04-06 14:00 ` Jeff King
2021-04-06 14:35 ` ZheNing Hu
2021-04-06 18:34 ` René Scharfe
2021-04-07 13:57 ` ZheNing Hu
2021-04-07 15:26 ` ZheNing Hu via GitGitGadget [this message]
2021-04-07 20:31 ` [PATCH v2] " Junio C Hamano
2021-04-08 12:05 ` ZheNing Hu
2021-04-07 21:27 ` Jeff King
2021-04-08 12:18 ` ZheNing Hu
2021-04-08 14:32 ` Jeff King
2021-04-08 14:43 ` ZheNing Hu
2021-04-08 14:51 ` Jeff King
2021-04-08 15:12 ` ZheNing Hu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.927.v2.git.1617809209164.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=adlternative@gmail.com \
--cc=chriscool@tuxfamily.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=hariom18599@gmail.com \
--cc=l.s.r@web.de \
--cc=peff@peff.net \
--cc=stolee@gmail.com \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.