Pruning unused methods

115 views
Skip to first unread message

Jim Minter

unread,
Nov 8, 2017, 7:26:58 PM11/8/17
to golan...@googlegroups.com
Hi,

I understand that if a codebase uses reflect.Value.Call() (among other
things) then link-time optimisation to prune unused methods is disabled.

As codebases expand and include third party libraries, it becomes harder
to prevent a reflect.Value.Call() or equivalent from slipping in
somewhere (not least from text/template), and the chances of the
optimisation being disabled inevitably grows. The knock-on effect is
that larger binaries are more likely to bloat (more).

Kubernetes is such a codebase. Unhappily, it imports a large number of
large third party client libraries, many of which it actually uses to a
rather limited extent. These client libraries are typically structured
around some "client" object and lots of methods, in all likelihood never
touched by reflect. Most of these methods end up unused, but cause
bloat because they can't be pruned automatically today.

One pattern is for such a client object to be used exclusively, or made
a non-exported member of some struct, within a package where reflect is
not used (example at [1]). In such circumstances, I wonder whether it
ought in principal to be detectable that reflect cannot be being used to
call arbitrary methods of the client object (due to visibility), and
that if this is the case across all usages, additional methods may be
prunable accordingly.

I carried out a very hacky test whereby I disabled the reflection
detection code at [2], and spotted that on my system the compiled
`kubelet` binary size reduced from 140MB to 88MB. `objdump -t` reported
that the number of methods emitted for go-cloudstack (an example large
third party client library in question) reduced to 51 (approximately
what I'd expect) from a previous figure of 3934.

Clearly my hack doesn't guarantee a working binary at the end, but it
provides an upper bound figure that suggests to me that there are
potentially substantial and worthwhile savings to be had against larger
binary sizes by improving the pruning code if possible.

Regards,

Jim Minter


[1]
https://github.com/kubernetes/kubernetes/blob/master/pkg/cloudprovider/providers/cloudstack/cloudstack.go#L52
[2]
https://github.com/golang/go/blob/master/src/cmd/link/internal/ld/deadcode.go#L79
Reply all
Reply to author
Forward
0 new messages