Re: [PATCH v2] Simplify maildir_delayed_parsing().
Alejandro Colomar via Mutt-dev <[email protected]> Mon, 20 Jul 2026 13:11:14 +0200
| Newsgroups | gmane.mail.mutt.devel |
|---|---|
| Message-ID | <al4CFF6gzkWynxZ-@devuan> |
--gkgqbwv34z7wg7zp Content-Type: text/plain; protected-headers=v1; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable From: Alejandro Colomar <[email protected]> To: [email protected] Subject: Re: [PATCH v2] Simplify maildir_delayed_parsing(). Message-ID: <al4CFF6gzkWynxZ-@devuan> References: <[email protected]> MIME-Version: 1.0 In-Reply-To: <[email protected]> Hi Kevin, On 2026-07-20T12:53:54+0800, Kevin J. McCarthy wrote: > Embed the DO_SORT() and the call to skip_duplicates() so I can > understand it better. Then remove the duplicate call to > mutt_buffer_printf(). >=20 > It seems the sort is delayed until after any initial md entries > without a header were first skipped, to make the sort faster. There > could be a very small number of "new" entries with a header, and if > they are not at the beginning this could speed the sort up a lot. >=20 > However putting the sort inside the loop with a DO_SORT() macro and a > call to skip_duplicates() makes the code over-complicated and hard to > understand. Place the maildir_sort() call before the loop and add > some comments. >=20 > Remove the header_parsed bit, because it is only set inside this loop, > and only checked inside this function. Since the function is not > called twice on the same md list, the header_parsed_bit field is not > needed. >=20 > Commit f2eef427 seems to indicate adding the sort was for reducing > seek time. I'm not a good judge of whether that's effective anymore, > but I added a comment to at least indicate why the sort is being done. > --- >=20 > This seems to be working, so I'll just send it out now. >=20 > The patch should look similar to the #3 and #4 from the last version. >=20 > The only difference is that I added back the "skip initial md entries > without md->h" before the sort. I think in many cases, for maildir, > there may be a small number of new entries. It's a bit random where > they are, but I'm still going to keep the optimization for now. >=20 > mh.c | 96 +++++++++++++++++++++--------------------------------------- > 1 file changed, 33 insertions(+), 63 deletions(-) It's difficult to review the patch, but assuming it works, the simplification seems nice. Have a lovely day! Alex >=20 > diff --git a/mh.c b/mh.c > index a74e94fb..ec9d07c6 100644 > --- a/mh.c > +++ b/mh.c > @@ -65,7 +65,6 @@ struct maildir > { > HEADER *h; > char *canon_fname; > - unsigned header_parsed:1; > #ifdef HAVE_DIRENT_D_INO > ino_t inode; > #endif /* HAVE_DIRENT_D_INO */ > @@ -1101,40 +1100,18 @@ static void mh_sort_natural(CONTEXT *ctx, struct = maildir **md) > *md =3D maildir_sort(*md, (size_t) -1, md_cmp_path); > } > =20 > -#if HAVE_DIRENT_D_INO > -static struct maildir *skip_duplicates(struct maildir *p, struct maildir= **last) > -{ > - /* > - * Skip ahead to the next non-duplicate message. > - * > - * p should never reach NULL, because we couldn't have reached this po= int unless > - * there was a message that needed to be parsed. > - * > - * the check for p->header_parsed is likely unnecessary since the dupe= s will most > - * likely be at the head of the list. but it is present for consisten= cy with > - * the check at the top of the for() loop in maildir_delayed_parsing(). > - */ > - while (!p->h || p->header_parsed) > - { > - *last =3D p; > - p =3D p->next; > - } > - return p; > -} > -#endif > - > /* > * This function does the second parsing pass > */ > -static void maildir_delayed_parsing(CONTEXT * ctx, struct maildir **md, > +static void maildir_delayed_parsing(CONTEXT *ctx, struct maildir **md, > progress_t *progress) > { > - struct maildir *p, *last =3D NULL; > + struct maildir *p; > +#if HAVE_DIRENT_D_INO > + struct maildir *last =3D NULL; > +#endif > BUFFER *fn =3D NULL; > int count; > -#if HAVE_DIRENT_D_INO > - int sort =3D 0; > -#endif > #if USE_HCACHE > header_cache_t *hc =3D NULL; > void *data; > @@ -1143,46 +1120,41 @@ static void maildir_delayed_parsing(CONTEXT * ctx= , struct maildir **md, > int ret; > #endif > =20 > -#if HAVE_DIRENT_D_INO > -#define DO_SORT() \ > - do \ > - { \ > - if (!sort) \ > - { \ > - muttdbg(4, "maildir: need to sort %s by inode", ctx->path); \ > - p =3D maildir_sort(p, (size_t) -1, md_cmp_inode); = \ > - if (!last) \ > - *md =3D p; = \ > - else \ > - last->next =3D p; = \ > - sort =3D 1; = \ > - p =3D skip_duplicates(p, &last); = \ > - mutt_buffer_printf(fn, "%s/%s", ctx->path, p->h->path); \ > - } \ > - } while (0) > -#else > -#define DO_SORT() /* nothing */ > -#endif > - > #if USE_HCACHE > hc =3D mutt_hcache_open(HeaderCache, ctx->path, NULL); > #endif > - > fn =3D mutt_buffer_pool_get(); > + p =3D *md; > =20 > - for (p =3D *md, count =3D 0; p; p =3D p->next, count++) > + /* > + * If available, sort by inode number to reduce seek time. > + */ > +#if HAVE_DIRENT_D_INO > + /* Skip over any initial entries without a header to make sorting fast= er. */ > + for (; p && !p->h; p =3D p->next) > + last =3D p; > + if (!p) > + goto cleanup; > + > + muttdbg(4, "sorting %s by inode", ctx->path); > + p =3D maildir_sort(p, (size_t) -1, md_cmp_inode); > + > + /* Reattach the initial entries without a header, if any, to the sorte= d list. > + * This is needed so that md is properly freed by the caller. */ > + if (last) > + last->next =3D p; > + else > + *md =3D p; > +#endif > + > + for (count =3D 0; p; p =3D p->next, count++) > { > - if (! (p && p->h && !p->header_parsed)) > - { > - last =3D p; > + if (!p->h) > continue; > - } > =20 > if (!ctx->quiet && progress) > mutt_progress_update(progress, count, -1); > =20 > - DO_SORT(); > - > mutt_buffer_printf(fn, "%s/%s", ctx->path, p->h->path); > =20 > #if USE_HCACHE > @@ -1215,7 +1187,6 @@ static void maildir_delayed_parsing(CONTEXT * ctx, = struct maildir **md, > =20 > if (maildir_parse_message(ctx->magic, mutt_b2s(fn), p->h->old, p->= h)) > { > - p->header_parsed =3D 1; > #if USE_HCACHE > if (ctx->magic =3D=3D MUTT_MH) > mutt_hcache_store(hc, p->h->path, p->h, 0, strlen, MUTT_GENERA= TE_UIDVALIDITY); > @@ -1229,16 +1200,15 @@ static void maildir_delayed_parsing(CONTEXT * ctx= , struct maildir **md, > } > mutt_hcache_free(&data); > #endif > - last =3D p; > } > + > +#if HAVE_DIRENT_D_INO > +cleanup: > +#endif > #if USE_HCACHE > mutt_hcache_close(hc); > #endif > - > mutt_buffer_pool_release(&fn); > - > -#undef DO_SORT > - > mh_sort_natural(ctx, md); > } > =20 > --=20 > 2.55.0 >=20 --=20 <https://www.alejandro-colomar.es> --gkgqbwv34z7wg7zp Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmpeAkwACgkQ64mZXMKQ wqmgrw/+Kgq7y8hqPRnzHJVR7SQx6Rlz6ZiltZ7tynz8wlReYQ21ioWZINq1A+pr LJoKSlrhEvkKFFVNPLNOr1FiqQfhyn2d7w51ZOgyxW1gT7FBkHoOOivZfpR5hpFi aDm5K/NmH1Yhzs2wq7vlMCh5VCQEnhKrReKOF8fexF7qC8x+BfSnSD7UtYFJjIHL wAjb3vQGDNsJg4NLTrBSdiLt6X9srN1d5zsvLprPrFa+DsTmBAF+rK6IH09chN2Q ciHfSwf99zi1GJd3rK7ofmNQTxOm+oY5Ew2WaAn06XfmAh9LeTfAn1OMlQCAJb1X aZNJbryMkEvnE0itr23rdNb3rdZn7tc81FD/MwvZcdD3M0HTYHlP9JzYd8P6LsRy 8bxa1+4pdwsAGi4tbJjz1AxjS3fVx9Q36IKqWZLmZ3V+mBI3Uj7rVce3I9mGOgKM Bkb3h+pLe77fE7OsFWT491A87eSzTP5r9xEZFgpFPiq6ivqHHdQhJn8zrsuH/eHt cykzkMR/MoTzPYsOfHJ5Pr90/cA8fqfSuqq/tdosZl5fo6qb+YIPyJ/PdiQLXtW3 +0HIiOhdS6Bx8sWjigrs7urjpp74oTtZGyP8dv+2i1jauOVnkqcMBDi59oZK4W3h VGoyEQkkwgaUoVfLUoN26k7VI40N6ZLSmmADVTWeGabgbr3zYnU= =QjC1 -----END PGP SIGNATURE----- --gkgqbwv34z7wg7zp--