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
List information: http://vger.kernel.org/majordomo-info.html
* 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.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).