JavaScript constructs/patterns to avoid on iOS Safari?
Asked Answered
S

4

28

I have a web app that contains a huge amount of generated JavaScript. The memory consumption differs by a factor 6 between running the web app in Chrome on a Desktop compared to running the web app in a UIWebView on an (updated) iPad.

What constructs or patterns should I avoid to get the memory consumption on iOS on par with that of Chrome?

Characterisation of the generated JavaScript:

  • The code is generated by Haxe.
  • The code is "object oriented" in that it makes heavy use of prototype, but in a civilized way.
  • The code makes heavy use of named indexes on JavaScript objects to implement hash tables.
  • There are a lot of strings, but hardly any string concatenations.

There does not appear to be any memory leaks; the excessive memory consumption on iOS shows immediately upon construction of the (fixed set of) Javascript objects.

Scrutable answered 19/8, 2015 at 14:23 Comment(7)
Note that UIWebView uses an older Javascript engine, it executes JS slower than Safari on iOS. If you run the code in Safari, does that run fast enough?Hernandez
The web app is supposed to be run from Safari, I only use UIWebView to allow XCode to see the memory consumption, which is what is the problem (ie. Safari reloads the page now and then). The execution speed is not really a problem.Scrutable
Mobile safari uses WKWebView so your app should instantiate one of those instead to do the comparison. You may also want to add v8 and javascriptcore to the tags so experts in those two JS engines can weigh in.Dysentery
Have you tried to open an issue on the dedicated github? github.com/HaxeFoundation/haxe/issuesOhmage
I don't think there are any patterns to apply to work around a flawed implementation. It might just need more memory than V8.Tigerish
If you use NSURLRequest, according to the following answer you will want to play with the cache policy to get more representative numbers. https://mcmap.net/q/504937/-uiwebview-taking-lots-of-memoryKavita
If you haven't any memory leaks as you said, than there is not a much what you can do here though. Im not very familiar with haxe, but looks like there are the root of your huge memory. Is it possible to see where are the junk of the memory coming from?Cristophercristy
O
2

Since your code does run well on the desktop it is probably some underlying quirk in iOS. Which I doubt you can fix using a more object oriented way of programming. Sure this might reduce the memory footprint a bit but not by a factor of 6.

UIWebView is quite notorious for creating memory leaks you could try to use the newer (iOS 8+) WKWebView has much better garbage collection.

Apple WKWebView Reference

Ola answered 30/12, 2015 at 12:38 Comment(0)
O
1

My Suggestion is that you look into the DOM part of your application. I don't think there is much optimization that can be done in your JavaScript structure. The weak link in mobile/tablets is usually the rendering process. If your goal is to reduce memory consumption, you can change the way your DOM works. try to to keep as minimum DOM nodes as you can, hide content (node-content) of of hidden DOM nodes. this kind of DOM manipulations , helped me in the past to make my web app more responsive , and to keep memory usage as low as possible .

Virtual Scroll , is something useful for keeping the dom as small as possible , virtual-scroll

Overstreet answered 28/1, 2016 at 8:31 Comment(0)
C
-1

A potential way you can try optimizing your code is via GWT (whose compiler, i believe, is a more optimizing compiler than haxe's js compiler).

I would first compile all your haxe code into java, then convert that into js via GWT,and see if the memory requirements remain similarly high.

If converting to java, then to GWT is too difficult, a close approximation is to use the google closure compiler on the resultant javascript generated via haxe. I m not sure if haxe is capable of outputting javascript in a way that is compatible with the ADVANCED_OPTIMIZATION mode (https://developers.google.com/closure/compiler/docs/compilation_levels#advanced_optimizations), which is what you'd need to do (otherwise, closure is no better than a simple code minimizer).

Cellarer answered 21/9, 2015 at 11:23 Comment(0)
M
-2

You mentioned it is using heavily of prototype. That could be a reason: if you think your objects can share same prototype try to do so; For Example:

baz.Bar = function () {
    // constructor
};

baz.Bar.prototype = {
    fooProp: ["bar", "foo"],
    foo : function (){
        //method
    }
};

baz.Bar2.prototype = baz.Bar.prototype;

You will notice baz.Bar2.prototype is pointing to baz.Bar.prototype. With this concept, you can save the memory to be allocated by baz.Bar2 because it sharing from baz.Bar.

Mano answered 6/10, 2015 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.