[Bug] Fatal iOS 13 memory leak when using TextToSpeach.SpeekAsync #1112
Description
Description
TextToSpeech.SpeakAsync
leaks significant memory when used with iOS 13. If repeated enough times, this will trigger the iOS kernel to terminate the app using TextToSpeech.SpeakAsync
.
Steps to Reproduce
- Clone demo project and open in VisualStudio Mac Enterprise.
- Set the deployment target to Debug > iPad Pro (11-inch) iOS 12.2 simulator.
- Build, deploy, run on simulator, and terminate app.
- In Solution Explorer, right click on Speak_n_Leak.iOS and select Start Profiling Item
- Upon Xamarin Profiler launch, be sure the right platform app and device are selected and then click [Next] to go to the configuration dialog.
- In the configuration dialog, in the Common Options section, select Minimum for Level of detail and then click [Start Profiling].
- App will start.
- In Xamarin Profiler, note the Allocations Max value.
- In the app, click the [Speak n Leak : n ] button.
- Observer how much (or little) the Allocations Max increases with each SpeakAsync.
- Click [Speak n Leak : n ] again when the counter reaches 100.
- In Xamarin Profiler, note the Allocations Max value.
- In Xamarin Profiler, stop the app.
- Quit Xamarin Profiler (or else you're likely to end up running the above app in the iOS 12.2 simulator again).
- In VisualStudio Mac, switch the deployment target to Debug > iPad Pro (11-inch) iOS 13.1 (or higher).
- Repeat steps 3 - 13 again.
Optional: Repeat all of the above using actual iOS device. Get similar results.
Optional: Try the following (I could not get this to work on the iOS 12 build of the app):
- Return to VisualStudio Mac, go to the menu bar, click on the ** Tools / (iOS and Mac) Instruments** to start Instruments application.
- In Instruments, in the Choose a profiling template for dialog, select the iPad Pro (11-inch) (13.1) > Speak_n_Leak target, verify that Allocations is selected, and click [Choose].
- Click the start button (top left in Instruments) to start profiling.
- Click the [Speak n Leak : 0] button and click it again (to stop) when it says [Speak n Leak: 10].
- Select the time span between the start and stop of the speaking.
Expected Behavior
- When profiling the app on a iOS 12 device (steps 3-10), the result of step 8 is 189.5MB:
- And step 12 is 198.3MB :
-
The change is 8.8MB (0.088MB per SpeakAsync)
-
When profiling using Instruments, expect the app to not create a bunch of live objects during speaking.
Actual Behavior
- When profiling the app on a iOS 13 device (steps 3-10), the result of step 8 is 142.4MB:
- And step 12 is 299.8MB :
-
The change is 157.4MB (1.57MB per SpeakAsync)
-
The result of Instruments profiling, before step 20 is 30.03MB:
- And after step 21 is 274.26MB:
**Notice the following: **
- The change in Persistent memory: 244.23MB (2.44 MB per SpeakAsync)!
- The large number of live TextToSpeachBundleSupport
objects at +500KB each!
- In our production app, on actual devices, this leak leads to the following fatal crash. This is because, if leaked to 1.4GB, iOS kernel will kill the app:
default 07:04:06.960949-0500 kernel 68888.699 memorystatus: killing_specific_process pid 822 [TMCS.iOS] (per-process-limit 10) 1484807KB - memorystatus_available_pages: 14750
default 07:04:07.231722-0500 ReportCrash starting prolongation transaction timer
default 07:04:07.231765-0500 ReportCrash Attempting to write jetsam report
default 07:04:07.231815-0500 ReportCrash Process TMCS.iOS [822] killed by jetsam reason per-process-limit
Basic Information
- Version with issue: all
- Last known good version: none
- IDE: VisualStudio Enterprise Mac Enterprise 8.4.5 (build 19)
- Platform Target Frameworks:
- iOS: info.plist Deployment Target from 8.0 to 13.0
- Nuget Packages: Xamarin.Forms 4.3.0.908675
- Affected Devices: all iOS 13 devices
Screenshots
See above