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

[PATCH v3 09/10] generate-cmdlist.sh: replace "grep' invocation with a shell version

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Nov 5, 2021, 14:08 UTC
Message-ID
<patch-v3-09.10-e2702bcc1d0-20211105T135058Z-avarab@gmail.com>
In-Reply-To
<cover-v3-00.10-00000000000-20211105T135058Z-avarab@gmail.com>

Replace the "grep" we run to exclude certain programs from the generated output with a pure-shell loop that strips out the comments, and sees if the "cmd" we're reading is on a list of excluded programs. This uses a trick similar to test_have_prereq() in test-lib-functions.sh.

On my *nix system this makes things quite a bit slower compared to
HEAD~:
o
  'sh generate-cmdlist.sh.old command-list.txt' ran
    1.56 ± 0.11 times faster than 'sh generate-cmdlist.sh command-list.txt'
   18.00 ± 0.19 times faster than 'sh generate-cmdlist.sh.master command-list.txt'

But when I tried running generate-cmdlist.sh 100 times in CI I found that it helped across the board even on OSX & Linux. I tried testing it in CI with this ad-hoc few-liner:

    for i in $(seq -w 0 11 | sort -nr)
    do
    	git show HEAD~$i:generate-cmdlist.sh >generate-cmdlist-HEAD$i.sh &&
    	git add generate-cmdlist* &&
    	cp t/t0000-generate-cmdlist.sh t/t00$i-generate-cmdlist.sh || : &&
    	perl -pi -e "s/HEAD0/HEAD$i/g" t/t00$i-generate-cmdlist.sh &&
    	git add t/t00*.sh
    done && git commit -m"generated it"

Here HEAD~02 and the t0002* file refers to this change, and HEAD~03 and t0003* file to the preceding commit, the relevant results were:

    linux-gcc:
    [12:05:33] t0002-generate-cmdlist.sh .. ok       14 ms ( 0.00 usr  0.00 sys +  3.64 cusr  3.09 csys =  6.73 CPU)
    [12:05:30] t0003-generate-cmdlist.sh .. ok       32 ms ( 0.00 usr  0.00 sys +  2.66 cusr  1.81 csys =  4.47 CPU)
    osx-gcc:
    [11:58:04] t0002-generate-cmdlist.sh .. ok    80081 ms ( 0.02 usr  0.02 sys + 17.80 cusr 10.07 csys = 27.91 CPU)
    [11:58:16] t0003-generate-cmdlist.sh .. ok    92127 ms ( 0.02 usr  0.01 sys + 22.54 cusr 14.27 csys = 36.84 CPU)
    vs-test:
    [12:03:14] t0002-generate-cmdlist.sh .. ok       30 s ( 0.02 usr  0.00 sys + 13.14 cusr 26.19 csys = 39.35 CPU)
    [12:03:20] t0003-generate-cmdlist.sh .. ok       32 s ( 0.00 usr  0.02 sys + 13.25 cusr 26.10 csys = 39.37 CPU)

I.e. even on *nix running 100 of these in a loop was up to ~2x faster in absolute runtime, I suspect it's due factors that are exacerbated in the CI, e.g. much slower process startup due to some platform limits, or a slower FS.

The "cut -d" change here is because we're not emitting the 40-character aligned output anymore, i.e. we'll get the output from command_list() now, not an as-is line from command-list.txt.

This also makes the parsing more reliable, as we could tweak the whitespace alignment without breaking this parser. Let's reword a now-inaccurate comment in "command-list.txt" describing that previous alignment limitation. We'll still need the "### command-list [...]" line due to the "Documentation/cmd-list.perl" logic added in 11c6659d85d (command-list: prepare machinery for upcoming "common groups" section, 2015-05-21).

There was a proposed change subsequent to this one[3] which continued moving more logic into the "command_list() function, i.e. replaced the "cut | tr | grep" chain in "category_list()" with an argument to "command_list()".

That change might have had a bit of an effect, but not as much as the preceding commit, so I decided to drop it. The relevant performance numbers from it were:

    linux-gcc:
    [12:05:33] t0001-generate-cmdlist.sh .. ok       13 ms ( 0.00 usr  0.00 sys +  3.33 cusr  2.78 csys =  6.11 CPU)
    [12:05:33] t0002-generate-cmdlist.sh .. ok       14 ms ( 0.00 usr  0.00 sys +  3.64 cusr  3.09 csys =  6.73 CPU)
    osx-gcc:
    [11:58:03] t0001-generate-cmdlist.sh .. ok    78416 ms ( 0.02 usr  0.01 sys + 11.78 cusr  6.22 csys = 18.03 CPU)
    [11:58:04] t0002-generate-cmdlist.sh .. ok    80081 ms ( 0.02 usr  0.02 sys + 17.80 cusr 10.07 csys = 27.91 CPU)
    vs-test:
    [12:03:20] t0001-generate-cmdlist.sh .. ok       34 s ( 0.00 usr  0.03 sys + 12.42 cusr 19.55 csys = 32.00 CPU)
    [12:03:14] t0002-generate-cmdlist.sh .. ok       30 s ( 0.02 usr  0.00 sys + 13.14 cusr 26.19 csys = 39.35 CPU)

As above HEAD~2 and t0002* are testing the code in this commit (and the line is the same), but HEAD~1 and t0001* are testing that dropped change in [3].

1. https://lore.kernel.org/git/cover-v2-00.10-00000000000-20211022T193027Z-avarab@gmail.com/
2. https://lore.kernel.org/git/patch-v2-08.10-83318d6c0da-20211022T193027Z-avarab@gmail.com/
3. https://lore.kernel.org/git/patch-v2-10.10-e10a43756d1-20211022T193027Z-avarab@gmail.com/
---
 command-list.txt    |  2 +-
 generate-cmdlist.sh | 24 ++++++++++++++++++++----
 2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/command-list.txt b/command-list.txt
index 04cde20c3da..675c28f0bd0 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -43,7 +43,7 @@
 # specified here, which can only have "guide" attribute and nothing
 # else.
 #
-### command list (do not change this line, also do not change alignment)
+### command list (do not change this line)
 # command name                          category [category] [category]
 git-add                                 mainporcelain           worktree
 git-am                                  mainporcelain
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index 9b7d6aea629..cfe0454d1de 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -6,12 +6,28 @@ die () {
 }
 
 command_list () {
-	eval "grep -ve '^#' $exclude_programs" <"$1"
+	while read cmd rest
+	do
+		case "$cmd" in
+		"#"* | '')
+			# Ignore comments and allow empty lines
+			continue
+			;;
+		*)
+			case "$exclude_programs" in
+			*":$cmd:"*)
+				;;
+			*)
+				echo "$cmd $rest"
+				;;
+			esac
+		esac
+	done <"$1"
 }
 
 category_list () {
 	command_list "$1" |
-	cut -c 40- |
+	cut -d' ' -f2- |
 	tr ' ' '\012' |
 	grep -v '^$' |
 	LC_ALL=C sort -u
@@ -69,11 +85,11 @@ print_command_list () {
 	echo "};"
 }
 
-exclude_programs=
+exclude_programs=:
 while test "--exclude-program" = "$1"
 do
 	shift
-	exclude_programs="$exclude_programs -e \"^$1 \""
+	exclude_programs="$exclude_programs$1:"
 	shift
 done
 
-- 
2.34.0.rc1.721.ga0c1db665bc
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 72 of 87 in “Why the Makefile is so eager to re-build & re-link”
  1. Ævar Arnfjörð BjarmasonJun 24, 2021
  2. Jeff KingJun 24, 2021
  3. Ævar Arnfjörð BjarmasonJun 24, 2021
  4. Johannes SixtJun 24, 2021
  5. Ævar Arnfjörð BjarmasonJun 25, 2021
  6. Ævar Arnfjörð BjarmasonJun 25, 2021
  7. Jeff KingJun 29, 2021
  8. 0/8 Makefile: make command-list.h 2-5x as fast with -jNÆvar Arnfjörð Bjarmason, Oct 20, 2021
  9. 1/8 command-list.txt: sort with "LC_ALL=C sort"Ævar Arnfjörð Bjarmason, Oct 20, 2021
  10. 2/8 generate-cmdlist.sh: trivial whitespace changeÆvar Arnfjörð Bjarmason, Oct 20, 2021
  11. 3/8 generate-cmdlist.sh: spawn fewer processesÆvar Arnfjörð Bjarmason, Oct 20, 2021
  12. 4/8 generate-cmdlist.sh: don't call get_categories() from category_list()Ævar Arnfjörð Bjarmason, Oct 20, 2021
  13. 5/8 generate-cmdlist.sh: run "grep | sort", not "sort | grep"Ævar Arnfjörð Bjarmason, Oct 20, 2021
  14. 6/8 generate-cmdlist.sh: replace for loop by printf's auto-repeat featureÆvar Arnfjörð Bjarmason, Oct 20, 2021
  15. Jeff KingOct 21, 2021
  16. Jeff KingOct 21, 2021
  17. 7/8 Makefile: stop having command-list.h depend on a wildcardÆvar Arnfjörð Bjarmason, Oct 20, 2021
  18. Jeff KingOct 21, 2021
  19. Junio C HamanoOct 21, 2021
  20. Øystein WalleOct 21, 2021
  21. 8/8 Makefile: assert correct generate-cmdlist.sh outputÆvar Arnfjörð Bjarmason, Oct 20, 2021
  22. Jeff KingOct 20, 2021
  23. Taylor BlauOct 20, 2021
  24. Ævar Arnfjörð BjarmasonOct 20, 2021
  25. Jeff KingOct 20, 2021
  26. Ævar Arnfjörð BjarmasonOct 21, 2021
  27. Taylor BlauOct 21, 2021
  28. Ævar Arnfjörð BjarmasonOct 22, 2021
  29. Jeff KingOct 21, 2021
  30. Junio C HamanoOct 21, 2021
  31. Ævar Arnfjörð BjarmasonOct 22, 2021
  32. Jeff KingOct 22, 2021
  33. Ævar Arnfjörð BjarmasonOct 22, 2021
  34. Eric SunshineOct 21, 2021
  35. 00/10 Makefile: make generate-cmdlist.sh much fasterÆvar Arnfjörð Bjarmason, Oct 22, 2021
  36. 01/10 command-list.txt: sort with "LC_ALL=C sort"Ævar Arnfjörð Bjarmason, Oct 22, 2021
  37. Junio C HamanoOct 25, 2021
  38. Ævar Arnfjörð BjarmasonOct 25, 2021
  39. Junio C HamanoOct 25, 2021
  40. 02/10 generate-cmdlist.sh: trivial whitespace changeÆvar Arnfjörð Bjarmason, Oct 22, 2021
  41. 03/10 generate-cmdlist.sh: spawn fewer processesÆvar Arnfjörð Bjarmason, Oct 22, 2021
  42. 04/10 generate-cmdlist.sh: don't call get_categories() from category_list()Ævar Arnfjörð Bjarmason, Oct 22, 2021
  43. 05/10 generate-cmdlist.sh: run "grep | sort", not "sort | grep"Ævar Arnfjörð Bjarmason, Oct 22, 2021
  44. 06/10 generate-cmdlist.sh: replace for loop by printf's auto-repeat featureÆvar Arnfjörð Bjarmason, Oct 22, 2021
  45. 07/10 generate-cmdlist.sh: stop sorting category linesÆvar Arnfjörð Bjarmason, Oct 22, 2021
  46. Jeff KingOct 25, 2021
  47. 08/10 generate-cmdlist.sh: do not shell out to "sed"Ævar Arnfjörð Bjarmason, Oct 22, 2021
  48. Jeff KingOct 25, 2021
  49. Jeff KingOct 25, 2021
  50. 10/10 generate-cmdlist.sh: replace "cut", "tr" and "grep" with pure-shellÆvar Arnfjörð Bjarmason, Oct 22, 2021
  51. Junio C HamanoOct 23, 2021
  52. 09/10 generate-cmdlist.sh: replace "grep' invocation with a shell versionÆvar Arnfjörð Bjarmason, Oct 22, 2021
  53. Junio C HamanoOct 23, 2021
  54. Junio C HamanoOct 23, 2021
  55. Taylor BlauOct 22, 2021
  56. Junio C HamanoOct 23, 2021
  57. Jeff KingOct 25, 2021
  58. 00/10 generate-cmdlist.sh: make it (and "make") run fasterÆvar Arnfjörð Bjarmason, Nov 5, 2021
  59. 01/10 command-list.txt: sort with "LC_ALL=C sort"Ævar Arnfjörð Bjarmason, Nov 5, 2021
  60. Junio C HamanoNov 5, 2021
  61. Ævar Arnfjörð BjarmasonNov 6, 2021
  62. Junio C HamanoNov 8, 2021
  63. 02/10 generate-cmdlist.sh: trivial whitespace changeÆvar Arnfjörð Bjarmason, Nov 5, 2021
  64. 03/10 generate-cmdlist.sh: spawn fewer processesÆvar Arnfjörð Bjarmason, Nov 5, 2021
  65. Junio C HamanoNov 5, 2021
  66. Ævar Arnfjörð BjarmasonNov 6, 2021
  67. 04/10 generate-cmdlist.sh: don't call get_categories() from category_list()Ævar Arnfjörð Bjarmason, Nov 5, 2021
  68. 05/10 generate-cmdlist.sh: run "grep | sort", not "sort | grep"Ævar Arnfjörð Bjarmason, Nov 5, 2021
  69. 06/10 generate-cmdlist.sh: replace for loop by printf's auto-repeat featureÆvar Arnfjörð Bjarmason, Nov 5, 2021
  70. 07/10 generate-cmdlist.sh: stop sorting category linesÆvar Arnfjörð Bjarmason, Nov 5, 2021
  71. 08/10 generate-cmdlist.sh: do not shell out to "sed"Ævar Arnfjörð Bjarmason, Nov 5, 2021
  72. 09/10 generate-cmdlist.sh: replace "grep' invocation with a shell versionÆvar Arnfjörð Bjarmason, Nov 5, 2021
  73. 10/10 generate-cmdlist.sh: don't parse command-list.txt thriceÆvar Arnfjörð Bjarmason, Nov 5, 2021
  74. Felipe ContrerasJun 25, 2021
  75. Eric SunshineJun 29, 2021
  76. Øystein WalleJun 24, 2021
  77. Øystein WalleJun 24, 2021
  78. Ævar Arnfjörð BjarmasonJun 25, 2021
  79. Documentation/Makefile: don't re-build on 'git version' changesÆvar Arnfjörð Bjarmason, Jul 2, 2021
  80. Junio C HamanoJul 2, 2021
  81. Ævar Arnfjörð BjarmasonJul 3, 2021
  82. Junio C HamanoJul 5, 2021
  83. Felipe ContrerasJul 3, 2021
  84. Ævar Arnfjörð BjarmasonJul 3, 2021
  85. Felipe ContrerasJul 3, 2021
  86. Junio C HamanoJul 5, 2021
  87. Felipe ContrerasJul 6, 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.