go: runtime, x/mobile: Severe performance regression since 1.18+ on iOS, when combined with Xcode

What version of Go are you using (go version)?

1.18 and higher

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

ios/arm64

What did you do?

We’ve been noticing for a while now that starting with Go 1.18, performance for iOS apps that contain libraries written in Go has severely regressed, to the point where such apps have become unusable under certain conditions. Under those conditions, an otherwise empty app that is calling an .xcframework generated from Go code using gomobile/bind, is experiencing severe fps drops (going as low as 5fps) even though CPU load is close to 0.

Interestingly, the problem:

  • Does not affect Go 1.17 and lower
  • Affects all Go version since 1.18 (including git head)
  • Is only present when the iOS device is connected to Xcode (either through USB or Wifi)
  • Is not present when the iOS device is connected to Xcode but the Xcode profiler is running.
  • Is not present when the iOS device is NOT connected to Xcode

See attached for a very simple Go project, which is then compiled for iOS with gomobile/bind and wrapped in a Swift wrapper project. For convenience and ease of reproducibility, we’ve including both the full Swift Xcode project as well as pre-compiled .xcframework files based on Go 1.16.15 and 1.18.9 (in addition to the full Go source code). The actual Go project does nothing more than simulate some load by calculating a few sha265 hashes and then sleeping.

To reproduce: simply run the project in XCode, and observe the fps counter.

Note that the drop in performance doesn’t just affect the Go code, but the full app containing the library, even code that does not depend in any way on the code being executed by the Go runtime.

Perhaps this is in some way connected to the stack frame pointers/new register-based calling convention introduced for ios/arm64 in Go 1.18?

What did you expect to see?

  • Performance to be roughly similar regardless of using Go 1.17 or 1.18+.
  • Performance to be roughly similar regardless of being connected to Xcode or not

What did you see instead?

Performance being fine with Go 1.17 and lower, while being very bad on Go 1.18 and higher. While CPU load is close to 0.

Project to reproduce

go-ios-performance-regression-project.zip

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Comments: 19 (10 by maintainers)

Most upvoted comments

Thanks. Interesting. If this is only for running when connected to XCode, I think you can set the environment variable GODEBUG=asyncpreemptoff=1 to disable async preemption. In the past I remember LLDB had hard time handling signals (seems better now?). Maybe that is related.