caddy icon indicating copy to clipboard operation
caddy copied to clipboard

Investigate missed deadcode elimination optimization

Open mohammed90 opened this issue 10 months ago • 4 comments

The linker's deadcode elimination may be partially disabled for variety of reasons, e.g. using MethodByName of the reflect package. It appears that Caddy pays this price due to the text/template package. The tool https://github.com/aarzilli/whydeadcode shows the call graph leading to a function that disables deadcode elimination.

It's not clear if avoiding those functions is possible in Caddy, but worth investigating and discussing. These are the ones I found in my attempts:

✗ $ go build -ldflags=-dumpdep . |& whydeadcode
text/template.(*state).evalField reachable from:
         text/template.(*state).evalFieldChain
         text/template.(*state).evalCommand
         text/template.(*state).evalPipeline
         text/template.(*state).walk
         text/template.(*Template).execute
         text/template.(*Template).Execute
         github.com/caddyserver/caddy/v2/cmd.init.0.func1.(*Command).SetHelpTemplate.tmpl.2
         github.com/caddyserver/caddy/v2/cmd.init.0.func1
         github.com/caddyserver/caddy/v2/cmd.init.0.func1·f
         github.com/caddyserver/caddy/v2/cmd.init.0
         github.com/caddyserver/caddy/v2/cmd..inittask
         go:main.inittasks
         _
$ go build -ldflags=-dumpdep . |& whydeadcode
text/template.(*state).evalField reachable from:
         text/template.(*state).evalFieldChain
         text/template.(*state).evalCommand
         text/template.(*state).evalPipeline
         text/template.(*state).walk
         text/template.(*Template).execute
         text/template.(*Template).Execute
         github.com/caddyserver/caddy/v2/cmd.init.0.func1.(*Command).SetVersionTemplate.tmpl.1
         github.com/caddyserver/caddy/v2/cmd.init.0.func1
         github.com/caddyserver/caddy/v2/cmd.init.0.func1·f
         github.com/caddyserver/caddy/v2/cmd.init.0
         github.com/caddyserver/caddy/v2/cmd..inittask
         go:main.inittasks
         _
$ go build -ldflags=-dumpdep . |& whydeadcode
text/template.(*state).evalField reachable from:
         text/template.(*state).evalFieldChain
         text/template.(*state).evalCommand
         text/template.(*state).evalPipeline
         text/template.(*state).walk
         text/template.(*Template).execute
         github.com/caddyserver/caddy/v2/modules/caddyhttp.buildHTTPServer
         github.com/caddyserver/caddy/v2/modules/caddyhttp.cmdRespond
         github.com/caddyserver/caddy/v2/modules/caddyhttp.cmdRespond·f
         github.com/caddyserver/caddy/v2/modules/caddyhttp.init.9.func1
         github.com/caddyserver/caddy/v2/modules/caddyhttp.init.9.func1·f
         github.com/caddyserver/caddy/v2/modules/caddyhttp.init.9
         github.com/caddyserver/caddy/v2/modules/caddyhttp..inittask
         go:main.inittasks
         _

mohammed90 avatar Mar 02 '25 19:03 mohammed90

I can't find the origin of this one, but it doesn't look easy to eliminate:

text/template.(*state).evalField reachable from:
         text/template.(*state).evalFieldChain
         text/template.(*state).evalCommand
         text/template.(*state).evalPipeline
         text/template.(*state).walk
         text/template.(*Template).execute
         html/template.(*Template).Execute
         golang.org/x/net/trace.RenderEvents
         golang.org/x/net/trace.Events
         golang.org/x/net/trace.Events·f
         golang.org/x/net/trace.init.0
         golang.org/x/net/trace..inittask
         go:main.inittasks

https://github.com/golang/go/issues/62024

ottenhoff avatar Mar 04 '25 04:03 ottenhoff

but it doesn't look easy to eliminate

Sigh. Thanks for taking a shot! I see now there's discussion at golang/go#72895.

mohammed90 avatar Mar 21 '25 01:03 mohammed90

I randomly stumbled on this issue and I don't know much about your code so I can't guarantee it's the same thing, but I know google.golang.org/grpc (which appears in your go.mod) imports golang.org/x/net/trace which uses a template in their init function, thus disabling DCE.

google.golang.org/grpc provides a build tag grpcnotrace to remove the import https://github.com/grpc/grpc-go/pull/6954.

Also for the record there is ongoing work to remove this use of templates https://github.com/golang/go/issues/62024.

pgimalac avatar Mar 26 '25 17:03 pgimalac

While I'm here thanks to https://github.com/spf13/cobra/pull/1956, github.com/spf13/cobra now doesn't disable DCE by default, so if you can remove the uses of SetHelpTemplate and SetVersionTemplate then you might be able to fix this 👍

pgimalac avatar Mar 26 '25 17:03 pgimalac