Cordova + Ionic 2/3 sadly unusable on iOS. PLEASE tell me i am wrong


#1

First, let me just say, we LOVE ionic … its amazing for all the obvious reasons…

What was not obvious to us? — all the problems as it relates to memory usage (leaks) on iOS.

We have been testing several iterations of ionic apps.

The most basic app alone, generated by the CLI using the Tabs template and then adding a simple form to one or more of those pages within it presents an ever increasing amount of Memory usage on iOS (safari UIWebView, WKWebView) when switching from one page to another … albeit, small increases … technically the app would crash eventually … but more importantly … APPLE will NOT allow an app that leaks memory in the app store.

Where this problem REALLY shines is within any app that makes use of Native features. Use a native feature like File or MediaPlugin and Memory usage grows with every instance by ENORMOUS amounts, DESPITE releasing instances after use.

Something as simple as recording a 5 second audio clip via the MediaPlugin and then deleting it and releasing the instance does NOT clear memory.

We are digging into the plugins to see if we can troubleshoot these issues, but thats an enormous undertaking … Apple’s tools do not really provide a way of tracking memory usage inside of a Cordova app.

Has ANYONE run into this problem or have ANY advice on how to avoid these memory issues?


#2

This is an interesting thread, because it names a specific method that causes the problem. Name of problem method: AVCaptureVideoDataOutputSampleBufferDelegate. Don’t know if it’s related to your issue.


#3

Well, there are thousands of Cordova apps in the App Store, serving millions of users. So the problems you mention can not be as bad you make them to be.

Have you tried submitting your app to the App Store and actually been rejected because this?
Have you experienced any real problems in you app because of these problems?


#4

We have slowly been stripping out functionality in our app to try to target whatever is causing the memory leaks… and are now down to a pretty bare bones app …

In addition to the plugins Ionic installs by default, StatusBar and Splashscreen, we additionally installed the Media and File plugins. Ionic Native 3.

Our app instantiates and loads a tabs page that has 2 tabs.

One tab loads an empty page.

The second tab, when selected, fires ionViewDidEnter() which instantiates the File and Media plugins:

import { Component } from '@angular/core';
import { IonicPage, ViewController } from 'ionic-angular';
import { File } from '@ionic-native/file';
import { MediaPlugin, MediaObject } from '@ionic-native/media';
/**
 * Generated class for the Home page.
 *
 * See http://ionicframework.com/docs/components/#navigation for more info
 * on Ionic pages and navigation.
 */
@IonicPage()
@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
})
export class Home {

  private audioInstanceRecord:MediaObject;
  private audioRecordToInternalURL;
  private audioRecordStatusCode:number = 0;
  private pageStatus:string = "";

  constructor(private viewCtrl: ViewController,
              private file: File,
              private mediaPlugin: MediaPlugin) {
  }

  createAFile() {
    this.file.createFile(this.file.documentsDirectory, 'audio.m4a', true)
    .then(res => this.audioRecordSetFilePaths(res))
    .catch(err => console.log('create file error:', err));
  }

  audioRecordSetFilePaths(data) {
    this.audioRecordToInternalURL = data.toInternalURL();

    this.mediaPlugin.create(this.audioRecordToInternalURL,(status)=>{
      this.audioRecordStatusCode = status
    }).then(file => this.audioInstanceRecord = file)
    .catch(e => console.log('Error opening media file', e));
  }

  startRecord(){
    this.audioInstanceRecord.startRecord();
    this.pageStatus = "recording...";
  }

  stopRecord(){
    this.audioInstanceRecord.stopRecord();
    this.pageStatus = "done recording.";
  }

  play() {
    this.audioInstanceRecord.play();
    this.pageStatus = "playing audio..."
  }
  pause() {
    this.audioInstanceRecord.pause();
    this.pageStatus = "paused audio."
  }

  dismiss() {
    let data = {foo: 'bar'};
    this.viewCtrl.dismiss(data).then(()=> {
    });
  }

  ionViewDidEnter() {
    this.createAFile();
  }

  ionViewWillLeave() {
    this.audioInstanceRecord.release();
    this.audioInstanceRecord = null;
    this.file.removeFile(this.file.documentsDirectory, 'audio.m4a')
    .then(res => console.log('remove:', res))
    .catch(err => console.log('create file error:', err));
  }

}

Which as you can see is pretty basic.

Now… NEVER MIND actually triggering those events, startRecord, Play etc …

WITHOUT even doing that …

JUST SWITCHING TABS back and forth ADDS to the Memory usage … approximately ~4MB with each time this second tab instantiates …

We release the audio instance on exiting among other things in there …

If something that simple adds to Memory usage thats never released … eventually the app WILL crash.

So with that i ask … and with all due respect … what good is Ionic if this is the case??

I’d LOVE for someone to tell me what i might be doing wrong …

But separate from this simple example … Our app is much more complex … and the memory usage is ENORMOUS … We have followed all conventions with regard to unsubscribing to observables where necessary, nulling out Arrays and properties where necessary … Honestly, it all just seems completely un-realistic to try and deploy an Ionic / Angular app into the real world with problems like this … i dunno … we are just VERY discouraged by all of this … and its not like we can really ask Ionic for help directly… they have enough on their hands … never mind memory leaks.

Here is our setup…

Cordova CLI: 6.5.0 
Ionic Framework Version: 3.0.1
Ionic CLI Version: 2.2.3
Ionic App Lib Version: 2.2.1
Ionic App Scripts Version: 1.3.0
ios-deploy version: 1.9.1 
ios-sim version: 5.0.13 
OS: macOS Sierra
Node Version: v7.9.0
Xcode version: Xcode 8.3 Build version 8W120l

#5

Just out of curiosity, could you try eliminating all the @IonicPage decorators and eagerly load everything into a single app module and see if that has any effect on the memory management issue?


#6

ugh … well @rapropos … its even worse…

When the app launches, in both scenarios… lazy loaded and also when removing all @IonicPage decorators, and eagerly loading all pages in app.module instead … The app starts out using approximately ~60MB of memory.

Upon switching Tabs back and fourth a bunch of times … in just a matter of about 2-3 minutes … It pushing 100MB …

This is BAD. This memory is never released. I’ve tried digging into the plugins themselves … everything seems correct … but if we have to become experts in C, well hence my point about having to hire a native developer … may as well go Native to begin with and skip Ionic?? …

Screen cap attached…


#7

Thanks for reporting back. If you can provide a publicly accessible repo, I expect the Ionic team would be interested in doing further investigation.


#8

Here you go… https://github.com/gitdisrupt/Ionic3iOSMemoryIssue

ANY HELP figuring this out greatly appreciated…

I have tested this same scenario in a modal as well vs switching tabs… seems to be the same result.


#9

It would be great if you could open an issue (I think framework is the right place; could conceivably get refiled to app-scripts, but I still think framework makes the most sense), include the link to that repo and a pointer to this thread.


#10

done: https://github.com/driftyco/ionic/issues/11446


#12

Just for context:

  • Is it uncommon for an iOS app to use ~95 MB of Memory?
  • What is the base memory use of a plain Cordova app? (Because that of course is the “Cordova tax” Ionic can’t influence at all)

#13

Great question …

I would assume you first have to ask yourself, which devices do you want your app to support?

If you need or want to support very old devices, well then the amount of acceptable memory usage would be a lot lower than that of newer devices …

With that said … Another factor would also be the total number of running applications on any given device … Most users tend not to quit applications they are not using. And all those apps running in the background are sucking up a lot of precious memory.

I saw somewhere that apple suggests an app in general should not require more than ~70Mb of memory in-order to run, but obviously that is just not realistic. I have to believe that a lot of those graphics intensive games consume a lot more than ~70Mb no?

My concern in this thread regards ever increasing memory usage inside of an Ionic / Cordova app … if an Ionic / Cordova app does not release memory for garbage collection, then any app written in Ionic / Cordova will eventually crash.


#14

You didn’t answer any of my questions.

Just as an additional data point: The thousands of Ionic apps out there don’t tend to crash uncontrollably all the time.

So I somehow think there is not really that big of a problem.


#15

Well i apologize, i am not sure how much memory an empty Cordova app uses … likely in the ~40mb range?

As to whether or not it is uncommon for an app to use ~95Mb of memory, i don’t know that either except to say that the larger / more complex a view is, the more memory it would require to run?

Like i was saying though, while great questions, they are just not relevant to the issue i raised here …

To your other points:

"… don’t tend to crash uncontrollably …"
Any application that has memory leaks WILL eventually crash… how quickly they will crash would depend on how long it needs to run in-order to crash … Leaks should be avoided wherever possible …

"… not that big of a problem."
Well, with all due respect … those leaks are in-fact a big problem … memory is precious … and there are still a lot of users out there with older devices.


#16

All true in theory, but Ionic apps are not crashing in masses. That’s a fact, otherwise the forum would be full of questions about this.

For now you didn’t show us anything that convinces me there are any real leaks: You didn’t show that native apps use less memory or don’t grow memory as the Ionic app, you didn’t show that Cordova apps use less memory or memory doesn’t grow as the Ionic app.

Does your app have any crashes because of memory leaks? If not, I think you are wasting your time.


#17

The memory leak I posted arose in iOS 10. That Cordova plugin worked fine in 9. I have done no investigation into the problem of the OP, but it is possible the new operating system changed something.


#18

The memory leak you posted also seems to be fixed.


#19

wait, regarding this thread? What was updated? Plugin? or Ionic?


#20

Also, make sure you are using the WK engine: https://github.com/driftyco/cordova-plugin-wkwebview-engine

We will make this the default engine soon.


#21

Ill give this another try … although ill say that i did try it and still saw the memory usage increases … the WKWebView created other problems unrelated to this thread … so for the time being i reverted back to the UIWebView