From 14c87455ad95039c8b754aa6caac0ee7ef7c3f98 Mon Sep 17 00:00:00 2001 From: rgodden <7768980+goddenrich@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:00:50 +0000 Subject: [PATCH 1/2] improve performance of whatinputs --- src/query/whatinputs.go | 27 +++++++------- src/query/whatinputs_test.go | 68 +++++++++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/query/whatinputs.go b/src/query/whatinputs.go index 70cd57d74..118cc4567 100644 --- a/src/query/whatinputs.go +++ b/src/query/whatinputs.go @@ -11,10 +11,10 @@ import ( // The targets are printed in the same order as the provided files, separated by a newline // Use printFiles to additionally echo the files themselves (i.e. print ) func WhatInputs(graph *core.BuildGraph, files []string, hidden, printFiles, ignoreUnknown bool) { - targets := graph.AllTargets() + inputs := whatInputs(graph.AllTargets(), files, hidden) for _, file := range files { - if inputLabels := whatInputs(targets, file, hidden); len(inputLabels) > 0 { + if inputLabels := inputs[file]; len(inputLabels) > 0 { for _, label := range inputLabels { if printFiles { fmt.Printf("%s ", file) @@ -27,25 +27,28 @@ func WhatInputs(graph *core.BuildGraph, files []string, hidden, printFiles, igno } } -func whatInputs(targets []*core.BuildTarget, file string, hidden bool) []core.BuildLabel { - labels := make(map[core.BuildLabel]struct{}) +func whatInputs(targets []*core.BuildTarget, files []string, hidden bool) map[string]core.BuildLabels { + filesMap := make(map[string]map[core.BuildLabel]struct{}, len(files)) + for _, file := range files { + filesMap[file] = make(map[core.BuildLabel]struct{}) + } for _, target := range targets { for _, source := range target.AllLocalSourcePaths() { - if source == file { + if _, ok := filesMap[source]; ok { label := target.Label if !hidden { label = target.Label.Parent() } - labels[label] = struct{}{} + filesMap[source][label] = struct{}{} } } } - - ret := make(core.BuildLabels, 0, len(labels)) - for label := range labels { - ret = append(ret, label) + ret := make(map[string]core.BuildLabels, len(filesMap)) + for file, labels := range filesMap { + for label := range labels { + ret[file] = append(ret[file], label) + } + sort.Sort(ret[file]) } - sort.Sort(ret) - return ret } diff --git a/src/query/whatinputs_test.go b/src/query/whatinputs_test.go index 09e82712b..d36b25489 100644 --- a/src/query/whatinputs_test.go +++ b/src/query/whatinputs_test.go @@ -25,8 +25,15 @@ func TestWhatInputsSingleTarget(t *testing.T) { addNewTarget(graph, pkg1, "target1", []core.BuildInput{fileSource}) graph.AddPackage(pkg1) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } func TestWhatInputsMultipleTargets(t *testing.T) { @@ -37,8 +44,16 @@ func TestWhatInputsMultipleTargets(t *testing.T) { addNewTarget(graph, pkg, "target2", []core.BuildInput{fileSource}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}, {PackageName: "package1", Name: "target2"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + {PackageName: "package1", Name: "target2"}, + }, + }, + inputLabels, + ) } func TestWhatInputsInternalTargetHidden(t *testing.T) { @@ -49,8 +64,15 @@ func TestWhatInputsInternalTargetHidden(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } func TestWhatInputsInternalTargetShown(t *testing.T) { @@ -61,8 +83,15 @@ func TestWhatInputsInternalTargetShown(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", true) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "_target1#srcs"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, true) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "_target1#srcs"}, + }, + }, + inputLabels, + ) } func TestWhatInputsSourceBothTargets(t *testing.T) { @@ -73,8 +102,15 @@ func TestWhatInputsSourceBothTargets(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{fileSource, internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", false) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } func TestWhatInputsSourceBothTargetsHidden(t *testing.T) { @@ -85,6 +121,14 @@ func TestWhatInputsSourceBothTargetsHidden(t *testing.T) { addNewTarget(graph, pkg, "target1", []core.BuildInput{fileSource, internalTarget.Label}) graph.AddPackage(pkg) - inputLabels := whatInputs(graph.AllTargets(), "package1/file1.txt", true) - assert.Equal(t, []core.BuildLabel{{PackageName: "package1", Name: "_target1#srcs"}, {PackageName: "package1", Name: "target1"}}, inputLabels) + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt"}, true) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "_target1#srcs"}, + {PackageName: "package1", Name: "target1"}, + }, + }, + inputLabels, + ) } From cc999d4bc46cf66d214caf0ba2e3203b0db5b35a Mon Sep 17 00:00:00 2001 From: rgodden <7768980+goddenrich@users.noreply.github.com> Date: Wed, 11 Mar 2026 10:50:16 +0000 Subject: [PATCH 2/2] comments --- src/query/whatinputs.go | 13 +++++----- src/query/whatinputs_test.go | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/query/whatinputs.go b/src/query/whatinputs.go index 118cc4567..1fcfb33bd 100644 --- a/src/query/whatinputs.go +++ b/src/query/whatinputs.go @@ -1,8 +1,10 @@ package query import ( + "cmp" "fmt" - "sort" + "maps" + "slices" "github.com/thought-machine/please/src/core" ) @@ -34,21 +36,18 @@ func whatInputs(targets []*core.BuildTarget, files []string, hidden bool) map[st } for _, target := range targets { for _, source := range target.AllLocalSourcePaths() { - if _, ok := filesMap[source]; ok { + if labels, ok := filesMap[source]; ok { label := target.Label if !hidden { label = target.Label.Parent() } - filesMap[source][label] = struct{}{} + labels[label] = struct{}{} } } } ret := make(map[string]core.BuildLabels, len(filesMap)) for file, labels := range filesMap { - for label := range labels { - ret[file] = append(ret[file], label) - } - sort.Sort(ret[file]) + ret[file] = slices.SortedFunc(maps.Keys(labels), func(a, b core.BuildLabel) int { return cmp.Compare(a.String(), b.String()) }) } return ret } diff --git a/src/query/whatinputs_test.go b/src/query/whatinputs_test.go index d36b25489..9bb56a937 100644 --- a/src/query/whatinputs_test.go +++ b/src/query/whatinputs_test.go @@ -56,6 +56,54 @@ func TestWhatInputsMultipleTargets(t *testing.T) { ) } +func TestWhatInputsMultipleFiles(t *testing.T) { + graph := core.NewGraph() + pkg := core.NewPackage("package1") + fileSource1 := core.FileLabel{File: "file1.txt", Package: pkg.Name} + addNewTarget(graph, pkg, "target1", []core.BuildInput{fileSource1}) + fileSource2 := core.FileLabel{File: "file2.txt", Package: pkg.Name} + addNewTarget(graph, pkg, "target2", []core.BuildInput{fileSource2}) + graph.AddPackage(pkg) + + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt", "package1/file2.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + "package1/file2.txt": { + {PackageName: "package1", Name: "target2"}, + }, + }, + inputLabels, + ) +} + +func TestWhatInputsMultiplePackages(t *testing.T) { + graph := core.NewGraph() + pkg1 := core.NewPackage("package1") + fileSource1 := core.FileLabel{File: "file1.txt", Package: pkg1.Name} + addNewTarget(graph, pkg1, "target1", []core.BuildInput{fileSource1}) + graph.AddPackage(pkg1) + pkg2 := core.NewPackage("package2") + fileSource2 := core.FileLabel{File: "file2.txt", Package: pkg2.Name} + addNewTarget(graph, pkg2, "target2", []core.BuildInput{fileSource2}) + graph.AddPackage(pkg2) + + inputLabels := whatInputs(graph.AllTargets(), []string{"package1/file1.txt", "package2/file2.txt"}, false) + assert.Equal(t, + map[string]core.BuildLabels{ + "package1/file1.txt": { + {PackageName: "package1", Name: "target1"}, + }, + "package2/file2.txt": { + {PackageName: "package2", Name: "target2"}, + }, + }, + inputLabels, + ) +} + func TestWhatInputsInternalTargetHidden(t *testing.T) { graph := core.NewGraph() pkg := core.NewPackage("package1")