git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 4/7] merge-ort: switch our strmaps over to using memory pools

From
Elijah Newren <newren@gmail.com>
Date
Jul 30, 2021, 02:30 UTC
Message-ID
<CABPp-BE8OEjcMrJO8uijLFsvvpQH9KA=a+p_6bH71Z6QxXLB6w@mail.gmail.com>
In-Reply-To
<YQMLBW6LAZmQ8nDz@coredump.intra.peff.net>
On Thu, Jul 29, 2021 at 2:09 PM Jeff King <peff@peff.net> wrote:
Show 30 quoted lines
>
> On Thu, Jul 29, 2021 at 12:37:52PM -0600, Elijah Newren wrote:
>
> > > Arguably, the existence of these function indirections is perhaps a sign
> > > that the strmap API should provide a version of the clear functions that
> > > takes "partial / not-partial" as a parameter.
> >
> > Are you suggesting a modification of str{map,intmap,set}_clear() to
> > take an extra parameter, or removing the
> > str{map,intmap,set}_partial_clear() functions and introducing new
> > functions that take a partial/not-partial parameter?  I think you're
> > suggesting the latter, and that makes more sense to me...but I'm
> > drawing blanks trying to come up with a reasonable function name.
>
> It does seem a shame to add the "partial" parameter to strmap_clear(),
> just because most callers don't need it (so they end up with this
> inscrutable "0" parameter).
>
> What if there was a flags field? Then it could be combined with the
> free_values parameter. The result is kind of verbose in two ways:
>
>  - now strset_clear(), etc, need a "flags" parameter, which they didn't
>    before (and is just "0" most of the time!)
>
>  - now "strmap_clear(foo, 1)" becomes "strmap_clear(foo, STRMAP_FREE_VALUES)".
>    That's a lot longer, though arguably it's easier to understand since
>    the boolean is explained.
>
> Having gone through the exercise, I am not sure it is actually making
> anything more readable (messy patch is below for reference).

Thanks for diving in. Since it's not clear if it's helping, I'll just take your earlier suggestion to rename the "strmap_func" variable to "strmap_clear_func" instead.

Show 262 quoted lines
>
> diff --git a/builtin/shortlog.c b/builtin/shortlog.c
> index 3e7ab1ca82..dfbdba53da 100644
> --- a/builtin/shortlog.c
> +++ b/builtin/shortlog.c
> @@ -242,7 +242,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
>                 insert_records_from_trailers(log, &dups, commit, &ctx, oneline_str);
>         }
>
> -       strset_clear(&dups);
> +       strset_clear(&dups, 0);
>         strbuf_release(&ident);
>         strbuf_release(&oneline);
>  }
> diff --git a/diffcore-rename.c b/diffcore-rename.c
> index 7e6b3e1b14..0c960111d1 100644
> --- a/diffcore-rename.c
> +++ b/diffcore-rename.c
> @@ -665,9 +665,10 @@ void partial_clear_dir_rename_count(struct strmap *dir_rename_count)
>
>         strmap_for_each_entry(dir_rename_count, &iter, entry) {
>                 struct strintmap *counts = entry->value;
> -               strintmap_clear(counts);
> +               strintmap_clear(counts, 0);
>         }
> -       strmap_partial_clear(dir_rename_count, 1);
> +       strmap_clear(dir_rename_count,
> +                    STRMAP_FREE_VALUES | STRMAP_PARTIAL_CLEAR);
>  }
>
>  static void cleanup_dir_rename_info(struct dir_rename_info *info,
> @@ -683,15 +684,15 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
>                 return;
>
>         /* idx_map */
> -       strintmap_clear(&info->idx_map);
> +       strintmap_clear(&info->idx_map, 0);
>
>         /* dir_rename_guess */
> -       strmap_clear(&info->dir_rename_guess, 1);
> +       strmap_clear(&info->dir_rename_guess, STRMAP_FREE_VALUES);
>
>         /* relevant_source_dirs */
>         if (info->relevant_source_dirs &&
>             info->relevant_source_dirs != dirs_removed) {
> -               strintmap_clear(info->relevant_source_dirs);
> +               strintmap_clear(info->relevant_source_dirs, 0);
>                 FREE_AND_NULL(info->relevant_source_dirs);
>         }
>
> @@ -716,7 +717,7 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
>
>                 if (!strintmap_get(dirs_removed, source_dir)) {
>                         string_list_append(&to_remove, source_dir);
> -                       strintmap_clear(counts);
> +                       strintmap_clear(counts, 0);
>                         continue;
>                 }
>
> @@ -1045,8 +1046,8 @@ static int find_basename_matches(struct diff_options *options,
>                 }
>         }
>
> -       strintmap_clear(&sources);
> -       strintmap_clear(&dests);
> +       strintmap_clear(&sources, 0);
> +       strintmap_clear(&dests, 0);
>
>         return renames;
>  }
> @@ -1700,7 +1701,7 @@ void diffcore_rename_extended(struct diff_options *options,
>         FREE_AND_NULL(rename_src);
>         rename_src_nr = rename_src_alloc = 0;
>         if (break_idx) {
> -               strintmap_clear(break_idx);
> +               strintmap_clear(break_idx, 0);
>                 FREE_AND_NULL(break_idx);
>         }
>         trace2_region_leave("diff", "write back to queue", options->repo);
> diff --git a/merge-ort.c b/merge-ort.c
> index 0fb942692a..0765e23577 100644
> --- a/merge-ort.c
> +++ b/merge-ort.c
> @@ -532,15 +532,10 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
>  {
>         struct rename_info *renames = &opti->renames;
>         int i;
> -       void (*strmap_func)(struct strmap *, int) =
> -               reinitialize ? strmap_partial_clear : strmap_clear;
> -       void (*strintmap_func)(struct strintmap *) =
> -               reinitialize ? strintmap_partial_clear : strintmap_clear;
> -       void (*strset_func)(struct strset *) =
> -               reinitialize ? strset_partial_clear : strset_clear;
> +       unsigned flags = reinitialize ? STRMAP_PARTIAL_CLEAR : 0;
>
>         if (opti->pool)
> -               strmap_func(&opti->paths, 0);
> +               strmap_clear(&opti->paths, flags);
>         else {
>                 /*
>                  * We marked opti->paths with strdup_strings = 0, so that
> @@ -550,15 +545,15 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
>                  * to these strings, it is time to deallocate them.
>                  */
>                 free_strmap_strings(&opti->paths);
> -               strmap_func(&opti->paths, 1);
> +               strmap_clear(&opti->paths, flags | STRMAP_FREE_VALUES);
>         }
>
>         /*
>          * All keys and values in opti->conflicted are a subset of those in
>          * opti->paths.  We don't want to deallocate anything twice, so we
>          * don't free the keys and we pass 0 for free_values.
>          */
> -       strmap_func(&opti->conflicted, 0);
> +       strmap_clear(&opti->conflicted, flags);
>
>         if (!opti->pool) {
>                 /*
> @@ -579,24 +574,24 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
>
>         /* Free memory used by various renames maps */
>         for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) {
> -               strintmap_func(&renames->dirs_removed[i]);
> -               strmap_func(&renames->dir_renames[i], 0);
> -               strintmap_func(&renames->relevant_sources[i]);
> +               strintmap_clear(&renames->dirs_removed[i], flags);
> +               strmap_clear(&renames->dir_renames[i], flags);
> +               strintmap_clear(&renames->relevant_sources[i], flags);
>                 if (!reinitialize)
>                         assert(renames->cached_pairs_valid_side == 0);
>                 if (i != renames->cached_pairs_valid_side &&
>                     -1 != renames->cached_pairs_valid_side) {
> -                       strset_func(&renames->cached_target_names[i]);
> -                       strmap_func(&renames->cached_pairs[i], 1);
> -                       strset_func(&renames->cached_irrelevant[i]);
> +                       strset_clear(&renames->cached_target_names[i], flags);
> +                       strmap_clear(&renames->cached_pairs[i], flags | STRMAP_FREE_VALUES);
> +                       strset_clear(&renames->cached_irrelevant[i], flags);
>                         partial_clear_dir_rename_count(&renames->dir_rename_count[i]);
>                         if (!reinitialize)
>                                 strmap_clear(&renames->dir_rename_count[i], 1);
>                 }
>         }
>         for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) {
> -               strintmap_func(&renames->deferred[i].possible_trivial_merges);
> -               strset_func(&renames->deferred[i].target_dirs);
> +               strintmap_clear(&renames->deferred[i].possible_trivial_merges, flags);
> +               strset_clear(&renames->deferred[i].target_dirs, flags);
>                 renames->deferred[i].trivial_merges_okay = 1; /* 1 == maybe */
>         }
>         renames->cached_pairs_valid_side = 0;
> @@ -1482,7 +1477,7 @@ static int handle_deferred_entries(struct merge_options *opt,
>                         if (ret < 0)
>                                 return ret;
>                 }
> -               strintmap_clear(&copy);
> +               strintmap_clear(&copy, 0);
>                 strintmap_for_each_entry(&renames->deferred[side].possible_trivial_merges,
>                                          &iter, entry) {
>                         const char *path = entry->key;
> diff --git a/strmap.c b/strmap.c
> index 4fb9f6100e..7343800df5 100644
> --- a/strmap.c
> +++ b/strmap.c
> @@ -37,10 +37,11 @@ void strmap_init_with_options(struct strmap *map,
>         map->strdup_strings = strdup_strings;
>  }
>
> -static void strmap_free_entries_(struct strmap *map, int free_values)
> +static void strmap_free_entries_(struct strmap *map, unsigned flags)
>  {
>         struct hashmap_iter iter;
>         struct strmap_entry *e;
> +       int free_values = flags & STRMAP_FREE_VALUES;
>
>         if (!map)
>                 return;
> @@ -64,16 +65,13 @@ static void strmap_free_entries_(struct strmap *map, int free_values)
>         }
>  }
>
> -void strmap_clear(struct strmap *map, int free_values)
> +void strmap_clear(struct strmap *map, unsigned flags)
>  {
> -       strmap_free_entries_(map, free_values);
> -       hashmap_clear(&map->map);
> -}
> -
> -void strmap_partial_clear(struct strmap *map, int free_values)
> -{
> -       strmap_free_entries_(map, free_values);
> -       hashmap_partial_clear(&map->map);
> +       strmap_free_entries_(map, flags);
> +       if (flags & STRMAP_PARTIAL_CLEAR)
> +               hashmap_partial_clear(&map->map);
> +       else
> +               hashmap_clear(&map->map);
>  }
>
>  static struct strmap_entry *create_entry(struct strmap *map,
> diff --git a/strmap.h b/strmap.h
> index 1e152d832d..d03d451654 100644
> --- a/strmap.h
> +++ b/strmap.h
> @@ -46,16 +46,14 @@ void strmap_init_with_options(struct strmap *map,
>                               struct mem_pool *pool,
>                               int strdup_strings);
>
> -/*
> - * Remove all entries from the map, releasing any allocated resources.
> - */
> -void strmap_clear(struct strmap *map, int free_values);
> +#define STRMAP_FREE_VALUES 1 /* 1 for historical compat, but we should probably
> +                               update callers to use the correct name) */
> +#define STRMAP_PARTIAL_CLEAR 2
>
>  /*
> - * Similar to strmap_clear() but leaves map->map->table allocated and
> - * pre-sized so that subsequent uses won't need as many rehashings.
> + * Remove all entries from the map, releasing any allocated resources.
>   */
> -void strmap_partial_clear(struct strmap *map, int free_values);
> +void strmap_clear(struct strmap *map, unsigned flags);
>
>  /*
>   * Insert "str" into the map, pointing to "data".
> @@ -148,14 +146,10 @@ static inline void strintmap_init_with_options(struct strintmap *map,
>         map->default_value = default_value;
>  }
>
> -static inline void strintmap_clear(struct strintmap *map)
> -{
> -       strmap_clear(&map->map, 0);
> -}
> -
> -static inline void strintmap_partial_clear(struct strintmap *map)
> +static inline void strintmap_clear(struct strintmap *map, unsigned flags)
>  {
> -       strmap_partial_clear(&map->map, 0);
> +       /* maybe clear STRMAP_FREE_VALUES bit for extra protection */
> +       strmap_clear(&map->map, flags);
>  }
>
>  static inline int strintmap_contains(struct strintmap *map, const char *str)
> @@ -232,14 +226,9 @@ static inline void strset_init_with_options(struct strset *set,
>         strmap_init_with_options(&set->map, pool, strdup_strings);
>  }
>
> -static inline void strset_clear(struct strset *set)
> -{
> -       strmap_clear(&set->map, 0);
> -}
> -
> -static inline void strset_partial_clear(struct strset *set)
> +static inline void strset_clear(struct strset *set, unsigned flags)
>  {
> -       strmap_partial_clear(&set->map, 0);
> +       strmap_clear(&set->map, flags);
>  }
>
>  static inline int strset_contains(struct strset *set, const char *str)
Previous: Jeff KingNext: Jeff King
Message 26 of 65 in “Final optimization batch (#15): use memory pools”
  1. 0/7 Final optimization batch (#15): use memory poolsElijah Newren via GitGitGadget, Jul 23, 2021
  2. 1/7 diffcore-rename: use a mem_pool for exact rename detection's hashmapElijah Newren via GitGitGadget, Jul 23, 2021
  3. Eric SunshineJul 23, 2021
  4. Elijah NewrenJul 23, 2021
  5. 2/7 merge-ort: set up a memory poolElijah Newren via GitGitGadget, Jul 23, 2021
  6. 3/7 merge-ort: add pool_alloc, pool_calloc, and pool_strndup wrappersElijah Newren via GitGitGadget, Jul 23, 2021
  7. Eric SunshineJul 23, 2021
  8. Derrick StoleeJul 26, 2021
  9. Elijah NewrenJul 28, 2021
  10. Jeff KingJul 29, 2021
  11. Elijah NewrenJul 30, 2021
  12. Jeff KingJul 30, 2021
  13. 5/7 diffcore-rename, merge-ort: add wrapper functions for filepair alloc/deallocElijah Newren via GitGitGadget, Jul 23, 2021
  14. 4/7 merge-ort: switch our strmaps over to using memory poolsElijah Newren via GitGitGadget, Jul 23, 2021
  15. 6/7 merge-ort: store filepairs and filespecs in our mem_poolElijah Newren via GitGitGadget, Jul 23, 2021
  16. 7/7 merge-ort: reuse path strings in pool_alloc_filespecElijah Newren via GitGitGadget, Jul 23, 2021
  17. Derrick StoleeJul 26, 2021
  18. Elijah NewrenJul 28, 2021
  19. 0/7 Final optimization batch (#15): use memory poolsElijah Newren via GitGitGadget, Jul 29, 2021
  20. 2/7 merge-ort: add pool_alloc, pool_calloc, and pool_strndup wrappersElijah Newren via GitGitGadget, Jul 29, 2021
  21. 1/7 diffcore-rename: use a mem_pool for exact rename detection's hashmapElijah Newren via GitGitGadget, Jul 29, 2021
  22. 4/7 merge-ort: switch our strmaps over to using memory poolsElijah Newren via GitGitGadget, Jul 29, 2021
  23. Jeff KingJul 29, 2021
  24. Elijah NewrenJul 29, 2021
  25. Jeff KingJul 29, 2021
  26. Elijah NewrenJul 30, 2021
  27. Jeff KingJul 30, 2021
  28. Ævar Arnfjörð BjarmasonJul 30, 2021
  29. Elijah NewrenJul 30, 2021
  30. Ævar Arnfjörð BjarmasonJul 30, 2021
  31. 3/7 merge-ort: set up a memory poolElijah Newren via GitGitGadget, Jul 29, 2021
  32. 5/7 diffcore-rename, merge-ort: add wrapper functions for filepair alloc/deallocElijah Newren via GitGitGadget, Jul 29, 2021
  33. 6/7 merge-ort: store filepairs and filespecs in our mem_poolElijah Newren via GitGitGadget, Jul 29, 2021
  34. 7/7 merge-ort: reuse path strings in pool_alloc_filespecElijah Newren via GitGitGadget, Jul 29, 2021
  35. Derrick StoleeJul 29, 2021
  36. Jeff KingJul 29, 2021
  37. Jeff KingJul 29, 2021
  38. Junio C HamanoJul 29, 2021
  39. Junio C HamanoJul 29, 2021
  40. Elijah NewrenJul 29, 2021
  41. Elijah NewrenJul 29, 2021
  42. Jeff KingJul 29, 2021
  43. 0/9 Final optimization batch (#15): use memory poolsElijah Newren via GitGitGadget, Jul 30, 2021
  44. 1/9 merge-ort: rename str{map,intmap,set}_func()Elijah Newren via GitGitGadget, Jul 30, 2021
  45. 2/9 diffcore-rename: use a mem_pool for exact rename detection's hashmapElijah Newren via GitGitGadget, Jul 30, 2021
  46. 3/9 merge-ort: add pool_alloc, pool_calloc, and pool_strndup wrappersElijah Newren via GitGitGadget, Jul 30, 2021
  47. 5/9 merge-ort: switch our strmaps over to using memory poolsElijah Newren via GitGitGadget, Jul 30, 2021
  48. 4/9 merge-ort: set up a memory poolElijah Newren via GitGitGadget, Jul 30, 2021
  49. 7/9 merge-ort: store filepairs and filespecs in our mem_poolElijah Newren via GitGitGadget, Jul 30, 2021
  50. 6/9 diffcore-rename, merge-ort: add wrapper functions for filepair alloc/deallocElijah Newren via GitGitGadget, Jul 30, 2021
  51. 8/9 merge-ort: reuse path strings in pool_alloc_filespecElijah Newren via GitGitGadget, Jul 30, 2021
  52. 9/9 merge-ort: remove compile-time ability to turn off usage of memory poolsElijah Newren via GitGitGadget, Jul 30, 2021
  53. Jeff KingJul 30, 2021
  54. 0/9 Final optimization batch (#15): use memory poolsElijah Newren via GitGitGadget, Jul 31, 2021
  55. 2/9 diffcore-rename: use a mem_pool for exact rename detection's hashmapElijah Newren via GitGitGadget, Jul 31, 2021
  56. 1/9 merge-ort: rename str{map,intmap,set}_func()Elijah Newren via GitGitGadget, Jul 31, 2021
  57. 3/9 merge-ort: add pool_alloc, pool_calloc, and pool_strndup wrappersElijah Newren via GitGitGadget, Jul 31, 2021
  58. 5/9 merge-ort: switch our strmaps over to using memory poolsElijah Newren via GitGitGadget, Jul 31, 2021
  59. 4/9 merge-ort: set up a memory poolElijah Newren via GitGitGadget, Jul 31, 2021
  60. 6/9 diffcore-rename, merge-ort: add wrapper functions for filepair alloc/deallocElijah Newren via GitGitGadget, Jul 31, 2021
  61. 8/9 merge-ort: reuse path strings in pool_alloc_filespecElijah Newren via GitGitGadget, Jul 31, 2021
  62. 7/9 merge-ort: store filepairs and filespecs in our mem_poolElijah Newren via GitGitGadget, Jul 31, 2021
  63. 9/9 merge-ort: remove compile-time ability to turn off usage of memory poolsElijah Newren via GitGitGadget, Jul 31, 2021
  64. Derrick StoleeAug 2, 2021
  65. Jeff KingAug 3, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.