testdata: avoid fmt in the implement test script

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.
pull/98/head
Daniel Martí 4 years ago
parent ad44350cd0
commit cdac2cd3d6

@ -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

Loading…
Cancel
Save