From cdac2cd3d66bc65194391990f509bacb2a175086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Fri, 14 Aug 2020 19:06:08 +0200 Subject: [PATCH] testdata: avoid fmt in the implement test script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like other tests, importing fmt results in quite a lot of extra work, due to the lack of build caching. In this particular test, we wanted fmt.Println so that T.String would be called in an indirect way, without defining or referencing Stringer interface in the main package. We can do that by rolling our own "tinyfmt" package in a dozen or so lines of code. Below is how 'go test -short -vet=off -run Script/implement' is affected, measured via benchcmd and benchstat: name old time/op new time/op delta GoTestScriptImplement 3.67s ± 9% 2.65s ±11% -27.68% (p=0.008 n=5+5) name old user-time/op new user-time/op delta GoTestScriptImplement 8.18s ± 4% 4.55s ± 9% -44.35% (p=0.008 n=5+5) name old sys-time/op new sys-time/op delta GoTestScriptImplement 1.27s ±12% 0.71s ±13% -44.07% (p=0.008 n=5+5) name old peak-RSS-bytes new peak-RSS-bytes delta GoTestScriptImplement 145MB ± 1% 145MB ± 2% ~ (p=1.000 n=5+5) All in all, we shave about one full second. It doesn't seem to affect the total 'go test -short' noticeably, but every little bit counts. --- testdata/scripts/implement.txt | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/testdata/scripts/implement.txt b/testdata/scripts/implement.txt index 234bd03..66695ee 100644 --- a/testdata/scripts/implement.txt +++ b/testdata/scripts/implement.txt @@ -1,13 +1,15 @@ -garble build main.go +garble build exec ./main -cmp stdout main.stdout +cmp stderr main.stderr ! binsubstr main$exe 'unexportedMethod' 'privateIface' +-- go.mod -- +module test/main -- main.go -- package main -import "fmt" +import "test/main/tinyfmt" type T string @@ -28,9 +30,28 @@ func (T) privateIface() {} var _ privateInterface = T("") func main() { - fmt.Println(T("foo")) - fmt.Println(T("foo").unexportedMethod()) + tinyfmt.Println(T("foo")) + tinyfmt.Println(T("foo").unexportedMethod()) } --- main.stdout -- +-- tinyfmt/fmt.go -- +package tinyfmt + +// Println emulates fmt.Println, and allows the main package to indirectly use +// T.String in a realistic way. We don't want to import fmt to avoid compiling +// too many packages, since we don't have build caching yet. +func Println(args ...interface{}) { + for _, arg := range args { + switch arg := arg.(type) { + case interface{String() string}: + print(arg.String()) + case string: + print(arg) + default: + panic("unsupported type") + } + } + println() +} +-- main.stderr -- String method for foo unexported method for foo