git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Stefan Beller <sbeller@google.com>
To: Michael Haggerty <mhagger@alum.mit.edu>
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
	"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>,
	"Jeff King" <peff@peff.net>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Brandon Williams" <bmwill@google.com>,
	"git@vger.kernel.org" <git@vger.kernel.org>
Subject: Re: [PATCH v2 02/21] prefix_ref_iterator: break when we leave the prefix
Date: Wed, 20 Sep 2017 13:25:43 -0700	[thread overview]
Message-ID: <CAGZ79kbwCAidGR3cgukdjckZVYwj+qbOikqN-e934uP1yk9Cuw@mail.gmail.com> (raw)
In-Reply-To: <2bb2e8ccb57eef8acbea5004167751a007a1bd2f.1505799700.git.mhagger@alum.mit.edu>

On Mon, Sep 18, 2017 at 11:22 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
> From: Jeff King <peff@peff.net>
>
> If the underlying iterator is ordered, then `prefix_ref_iterator` can
> stop as soon as it sees a refname that comes after the prefix. This
> will rarely make a big difference now, because `ref_cache_iterator`
> only iterates over the directory containing the prefix (and usually
> the prefix will span a whole directory anyway). But if *hint, hint* a
> future reference backend doesn't itself know where to stop the
> iteration, then this optimization will be a big win.
>
> Note that there is no guarantee that the underlying iterator doesn't
> include output preceding the prefix, so we have to skip over any
> unwanted references before we get to the ones that we want.
>
> Signed-off-by: Jeff King <peff@peff.net>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
>  refs/iterator.c | 32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
>
> diff --git a/refs/iterator.c b/refs/iterator.c
> index c475360f0a..bd35da4e62 100644
> --- a/refs/iterator.c
> +++ b/refs/iterator.c
> @@ -287,6 +287,20 @@ struct prefix_ref_iterator {
>         int trim;
>  };
>
> +/* Return -1, 0, 1 if refname is before, inside, or after the prefix. */
> +static int compare_prefix(const char *refname, const char *prefix)
> +{
> +       while (*prefix) {
> +               if (*refname != *prefix)
> +                       return ((unsigned char)*refname < (unsigned char)*prefix) ? -1 : +1;

This looks interesting.

We get a signed char* , cast it to unsigned char* and then
compare byte by byte.

The cast lead me to think that this should work for non-ASCII
(e.g. ANSI?), but given that there are multi-byte characters (e.g.
UTF-8) depending on your encoding used, we may not assume
that in the given encoding the characters order by their byte order?

But this compare function is not to order by the natural encoding order,
but it's used to detect the '0' at the end of prefix, which orders
before *any* unsigned char.

We cannot enhance starts_with for this case as we'd have to invert
the return value to differentiate between the prefix ordering before
or after the given string.

Essentially compare_prefix wants to provide the same return
value as `strncmp(refname, prefix, min(strlen(refname), strlen(prefix)));`
except that it is optimized as we do not have to walk over a string
multiple times (to determine length and then pass it to compare).

Feel free to ignore the rambling, I just had to sort my thoughts.
The patch looks good.

Thanks,
Stefan

> +
> +               refname++;
> +               prefix++;
> +       }
> +
> +       return 0;
> +}
> +
>  static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
>  {
>         struct prefix_ref_iterator *iter =
> @@ -294,9 +308,25 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
>         int ok;
>
>         while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
> -               if (!starts_with(iter->iter0->refname, iter->prefix))
> +               int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
> +
> +               if (cmp < 0)
>                         continue;
>
> +               if (cmp > 0) {
> +                       /*
> +                        * If the source iterator is ordered, then we
> +                        * can stop the iteration as soon as we see a
> +                        * refname that comes after the prefix:
> +                        */
> +                       if (iter->iter0->ordered) {
> +                               ok = ref_iterator_abort(iter->iter0);
> +                               break;
> +                       } else {
> +                               continue;
> +                       }
> +               }
> +
>                 if (iter->trim) {
>                         /*
>                          * It is nonsense to trim off characters that
> --
> 2.14.1
>

  reply	other threads:[~2017-09-20 20:25 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-19  6:22 [PATCH v2 00/21] Read `packed-refs` using mmap() Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 01/21] ref_iterator: keep track of whether the iterator output is ordered Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 02/21] prefix_ref_iterator: break when we leave the prefix Michael Haggerty
2017-09-20 20:25   ` Stefan Beller [this message]
2017-09-21  4:59     ` Jeff King
2017-09-21 17:29       ` Stefan Beller
2017-09-21  7:42     ` Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 03/21] packed_ref_cache: add a backlink to the associated `packed_ref_store` Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 04/21] die_unterminated_line(), die_invalid_line(): new functions Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 05/21] read_packed_refs(): use mmap to read the `packed-refs` file Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 06/21] read_packed_refs(): only check for a header at the top of the file Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 07/21] read_packed_refs(): make parsing of the header line more robust Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 08/21] read_packed_refs(): read references with minimal copying Michael Haggerty
2017-09-20 18:27   ` Jeff King
2017-09-21  7:34     ` Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 09/21] packed_ref_cache: remember the file-wide peeling state Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 10/21] mmapped_ref_iterator: add iterator over a packed-refs file Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 11/21] mmapped_ref_iterator_advance(): no peeled value for broken refs Michael Haggerty
2017-09-20 18:29   ` Jeff King
2017-09-19  6:22 ` [PATCH v2 12/21] packed-backend.c: reorder some definitions Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 13/21] packed_ref_cache: keep the `packed-refs` file mmapped if possible Michael Haggerty
2017-09-19 12:44   ` Michael Haggerty
2017-09-24  6:56     ` Junio C Hamano
2017-09-20 18:40   ` Jeff King
2017-09-20 18:51     ` Jeff King
2017-09-21  8:04       ` Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 14/21] read_packed_refs(): ensure that references are ordered when read Michael Haggerty
2017-09-20 18:50   ` Jeff King
2017-09-21  8:27     ` Michael Haggerty
2017-09-25 15:44       ` Johannes Schindelin
2017-09-19  6:22 ` [PATCH v2 15/21] packed_ref_iterator_begin(): iterate using `mmapped_ref_iterator` Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 16/21] packed_read_raw_ref(): read the reference from the mmapped buffer Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 17/21] ref_store: implement `refs_peel_ref()` generically Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 18/21] packed_ref_store: get rid of the `ref_cache` entirely Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 19/21] ref_cache: remove support for storing peeled values Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 20/21] mmapped_ref_iterator: inline into `packed_ref_iterator` Michael Haggerty
2017-09-19  6:22 ` [PATCH v2 21/21] packed-backend.c: rename a bunch of things and update comments Michael Haggerty
2017-09-19 19:53 ` [PATCH v2 00/21] Read `packed-refs` using mmap() Johannes Schindelin
2017-09-20 18:57 ` Jeff King
2017-09-25 15:55   ` Johannes Schindelin

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=CAGZ79kbwCAidGR3cgukdjckZVYwj+qbOikqN-e934uP1yk9Cuw@mail.gmail.com \
    --to=sbeller@google.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=avarab@gmail.com \
    --cc=bmwill@google.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=mhagger@alum.mit.edu \
    --cc=pclouds@gmail.com \
    --cc=peff@peff.net \
    /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).