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

[PATCH v3 0/5] Skip 'cache_tree_update()' when 'prime_cache_tree()' is called immediate after

From
Victoria Dye via GitGitGadget <gitgitgadget@gmail.com>
Date
Nov 10, 2022, 19:06 UTC
Message-ID
<pull.1411.v3.git.1668107165.gitgitgadget@gmail.com>
In-Reply-To
<pull.1411.v2.git.1668045438.gitgitgadget@gmail.com>

Following up on a discussion [1] around cache tree refreshes in 'git reset', this series updates callers of 'unpack_trees()' to skip its internal invocation of 'cache_tree_update()' when 'prime_cache_tree()' is called immediately after 'unpack_trees()'. 'cache_tree_update()' can be an expensive operation, and it is redundant when 'prime_cache_tree()' clears and rebuilds the cache tree from scratch immediately after.

The first patch adds a test directly comparing the execution time of 'prime_cache_tree()' with that of 'cache_tree_update()'. The results show that on a fully-valid cache tree, they perform the same, but on a partially- or fully-invalid cache tree (the more likely case in commands with the aforementioned redundancy), 'prime_cache_tree()' is faster.

The second patch introduces the 'skip_cache_tree_update' option for 'unpack_trees()', but does not use it yet.

The remaining three patches update callers that make the aforementioned redundant cache tree updates. The performance impact on these callers ranges from "negligible" (in 'rebase') to "substantial" (in 'read-tree') - more details can be found in the commit messages of the patch associated with the affected code path.

Changes since V2 ================

 * Cleaned up option handling & provided more informative error messages in
   'test-tool cache-tree'. The changes don't affect any behavior in the
   added tests & 'test-tool cache-tree' won't be used outside of
   development, but the improvements here will help future readers avoid
   propagating error-prone implementations.
   * Note that the suggestion to change the "unknown subcommand" error to a
     'usage()' error was not taken, as it would be somewhat cumbersome to
     use a formatted string with it. This is in line with other custom
     subcommand parsing in Git, such as in 'fsmonitor--daemon.c'.

Changes since V1 ================

 * Rewrote 'p0090' to more accurately and reliably test 'prime_cache_tree()'
   vs. 'cache_tree_update()'.
   * Moved iterative cache tree update out of C and into the shell tests (to
     avoid potential runtime optimizations)
   * Added a "control" test to document how much of the execution time is
     startup overhead
   * Added tests demonstrating performance in partially-invalid cache trees.
 * Fixed the use of 'prime_cache_tree()' in 'test-tool cache-tree', changing
   it from using the tree at HEAD to the current cache tree.
Thanks!
 * Victoria

[1] https://lore.kernel.org/git/xmqqlf30edvf.fsf@gitster.g/ [2] https://lore.kernel.org/git/f4881b7455b9d33c8a53a91eda7fbdfc5d11382c.1627066238.git.jonathantanmy@google.com/

Victoria Dye (5):
  cache-tree: add perf test comparing update and prime
  unpack-trees: add 'skip_cache_tree_update' option
  reset: use 'skip_cache_tree_update' option
  read-tree: use 'skip_cache_tree_update' option
  rebase: use 'skip_cache_tree_update' option
 Makefile                           |  1 +
 builtin/read-tree.c                |  4 ++
 builtin/reset.c                    |  2 +
 reset.c                            |  1 +
 sequencer.c                        |  1 +
 t/helper/test-cache-tree.c         | 64 ++++++++++++++++++++++++++++++
 t/helper/test-tool.c               |  1 +
 t/helper/test-tool.h               |  1 +
 t/perf/p0006-read-tree-checkout.sh |  8 ++++
 t/perf/p0090-cache-tree.sh         | 36 +++++++++++++++++
 t/perf/p7102-reset.sh              | 21 ++++++++++
 t/t1022-read-tree-partial-clone.sh |  2 +-
 unpack-trees.c                     |  3 +-
 unpack-trees.h                     |  3 +-
 14 files changed, 145 insertions(+), 3 deletions(-)
 create mode 100644 t/helper/test-cache-tree.c
 create mode 100755 t/perf/p0090-cache-tree.sh
 create mode 100755 t/perf/p7102-reset.sh
base-commit: 3b08839926fcc7cc48cf4c759737c1a71af430c1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1411%2Fvdye%2Ffeature%2Fcache-tree-optimization-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1411/vdye/feature/cache-tree-optimization-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1411
Range-diff vs v2:
 1:  833519d87c8 ! 1:  2b48a684156 cache-tree: add perf test comparing update and prime
     @@ Commit message
          partially invalid (e.g., 'git reset --hard'), 'prime_cache_tree()' will
          likely perform better than 'cache_tree_update()' in typical cases.
      
     +    Helped-by: SZEDER Gábor <szeder.dev@gmail.com>
          Signed-off-by: Victoria Dye <vdye@github.com>
      
       ## Makefile ##
     @@ t/helper/test-cache-tree.c (new)
      +
      +	setup_git_directory();
      +
     -+	parse_options(argc, argv, NULL, options, test_cache_tree_usage, 0);
     ++	argc = parse_options(argc, argv, NULL, options, test_cache_tree_usage, 0);
      +
      +	if (read_cache() < 0)
     -+		die("unable to read index file");
     ++		die(_("unable to read index file"));
      +
      +	oidcpy(&oid, &the_index.cache_tree->oid);
      +	tree = parse_tree_indirect(&oid);
     @@ t/helper/test-cache-tree.c (new)
      +			cache_tree_invalidate_path(&the_index, the_index.cache[i * interval]->name);
      +	}
      +
     -+	if (!argc)
     -+		die("Must specify subcommand");
     ++	if (argc != 1)
     ++		usage_with_options(test_cache_tree_usage, options);
      +	else if (!strcmp(argv[0], "prime"))
      +		prime_cache_tree(the_repository, &the_index, tree);
      +	else if (!strcmp(argv[0], "update"))
      +		cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
      +	/* use "control" subcommand to specify no-op */
      +	else if (!!strcmp(argv[0], "control"))
     -+		die("Unknown command %s", argv[0]);
     ++		die(_("Unhandled subcommand '%s'"), argv[0]);
      +
      +	return 0;
      +}
 2:  b015a4f531c = 2:  0e03614f0fd unpack-trees: add 'skip_cache_tree_update' option
 3:  4f6039971b8 = 3:  386f18ca36a reset: use 'skip_cache_tree_update' option
 4:  5a646bc47c9 = 4:  ea5c82ce992 read-tree: use 'skip_cache_tree_update' option
 5:  fffe2fc17ed = 5:  100c01e936c rebase: use 'skip_cache_tree_update' option
-- 
gitgitgadget
Previous: Derrick StoleeNext: Victoria Dye via GitGitGadget
Message 22 of 31 in “Skip 'cache_tree_update()' when 'prime_cache_tree()' is called immediate after”
  1. 0/5 Skip 'cache_tree_update()' when 'prime_cache_tree()' is called immediate afterVictoria Dye via GitGitGadget, Nov 8, 2022
  2. 1/5 cache-tree: add perf test comparing update and primeVictoria Dye via GitGitGadget, Nov 8, 2022
  3. SZEDER GáborNov 10, 2022
  4. 3/5 reset: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 8, 2022
  5. 2/5 unpack-trees: add 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 8, 2022
  6. 5/5 rebase: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 8, 2022
  7. 4/5 read-tree: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 8, 2022
  8. Derrick StoleeNov 9, 2022
  9. Victoria DyeNov 9, 2022
  10. Derrick StoleeNov 10, 2022
  11. Taylor BlauNov 9, 2022
  12. 0/5 Skip 'cache_tree_update()' when 'prime_cache_tree()' is called immediate afterVictoria Dye via GitGitGadget, Nov 10, 2022
  13. 3/5 reset: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  14. 2/5 unpack-trees: add 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  15. 1/5 cache-tree: add perf test comparing update and primeVictoria Dye via GitGitGadget, Nov 10, 2022
  16. 5/5 rebase: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  17. Phillip WoodNov 10, 2022
  18. Victoria DyeNov 10, 2022
  19. 4/5 read-tree: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  20. Taylor BlauNov 10, 2022
  21. Derrick StoleeNov 10, 2022
  22. 0/5 Skip 'cache_tree_update()' when 'prime_cache_tree()' is called immediate afterVictoria Dye via GitGitGadget, Nov 10, 2022
  23. 1/5 cache-tree: add perf test comparing update and primeVictoria Dye via GitGitGadget, Nov 10, 2022
  24. 2/5 unpack-trees: add 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  25. 3/5 reset: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  26. 5/5 rebase: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  27. 4/5 read-tree: use 'skip_cache_tree_update' optionVictoria Dye via GitGitGadget, Nov 10, 2022
  28. SZEDER GáborNov 10, 2022
  29. Victoria DyeNov 10, 2022
  30. Taylor BlauNov 11, 2022
  31. Derrick StoleeNov 14, 2022

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.