New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/go: link speed slow with ldflags -X #28933
Comments
cc @bcmills On my phone, but I wonder whether adding/modifying ldflags causes cmd/go to recompile as well as re-link. |
It doesn't look like it recompiles, it's the linker step that gets slower. I'm a novice when it comes to the low level things but it looks like things only slow down during the link step. |
@groob is the slowness still present in 1.10? Did 1.11 get slower for you? Thanks. |
I couldn't reproduce this: (t2.go is your example with cloud.google.com/go/storage)
There is no significant time change with or without -X. I suspect that in your timing, without -X the "go" command just picks the result from the build cache, whereas with -X (especially with different value each time), it actually runs the linker. Could you use |
@cherrymui to see the difference build t2.go twice without -X. or with X but with See 1st, vs follow up builds:
And first vs followup when id changes.
|
Please show us the |
sure.
|
Ah something interesting. After I build |
Thanks. The build cache does not actually cache fully linked binaries, because of their size. Instead, it computes the build ID of the link, and compares that to the build ID recorded in the binary. In your case you are using the same binary, so whether the link is fast or slow depends entirely on how the last build was run. If you consistently run |
Is there something that can be improved here? I could remove the build date from flags, or make it less granular, but it also reduces the usefulness. Many projects (kubernetes for example) tag the build with a timestamp, it would be nice if there was some workaround for this. |
I think we need to be clear on what is happening. In the fast link case, there is nothing to do. The executable is already up to date. In the slow link case, the executable is not up to date, and the linker has to be invoked. So the issue is not whether the linker runs faster or slower, it's whether the linker needs to be run at all. If you want to build with a timestamp, then by definition if the timestamp changes then the executable is out of date, and the linker has to be run. So once you've made that decision, you have to run the linker, and you will see the build time effect of that. So when you ask whether there is something that can be improved, the answer is: don't build with a timestamp. If you want to build with a timestamp, then you have to invoke the linker, at least within the granularity of the timestamp. That's not optional. (One approach you could use would be to make the timestamp a separate step. Run with |
(feel free to point me to Slack instead). Could you elaborate on how to go about doing what you're suggesting? How would one do this:
I was going to work around this by having two make targets, one for building with timestamp and one without. But perhaps I'm missing a easier way. |
|
Sounds like this is sorted out sufficiently. I'm going to close this issue; please comment if you'd like me to re-open it. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
NOTE, I'm attaching this example as a zip archive.
linkflags.zip
I use
-ldflags -X build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
during the build step to attach a build time and current version to my go program. Having a dynamic field like date in ldflags increases the build time in projects significantly.Starting with a simple main.go:
When I use a static value like =X, the first time the build is slower, but then I see faster build times.
Note: I'm using
-w
due to #26318Now when, the ldflags value changes between builds, the time goes up:
In a real project with lots of transitive dependencies this build time is much worse. In our relatively large codebase it takes 4 seconds with ldflags, and 1 second without to create a build. Even modifying this example to introduce the GCP library as a dependency shows a significant increase.
-ldflags "-w -v="2"
OutputWhat did you expect to see?
go build
builds a go program fast.What did you see instead?
Slow
go build
times.The text was updated successfully, but these errors were encountered: