hadders
hadders

Reputation: 81

Javascript runs slowly in Safari / iPad2 after loading 200mb worth of new Images(). Why might this be?

Does anyone know why Javascript performance would be affected by the loading of lots of external JPG/PNG images into HTML5 Image() objects, totalling approx 200Mb-250Mb. Performance also seems to be affected by cache. Ie. if the cache is full(-ish) from previous browsing the performance on the current site is greatly reduced.

There are 2 says i can crudely solve it.

  1. clear cache manually.
  2. minimise browser, wait about 20 secs and re-open the browser after which time the iOS/browser has reclaimed the memory and runs the JS as it should.

I would have expected the iOS to reclaim required memory to run the current task, but it seems not. Another workaround is to load 200Mb of 'cache clearing' images into Image() objects, then remove these by setting the src = "". This does seem to help, but its not an elegant solution...

please help?

Upvotes: 0

Views: 1330

Answers (2)

First and foremost read the excellent post on LinkedIn Engineering blog. Read it carefully and check if there are some optimizations that you can also try in your application. If you tried all of them and that still haven't solved your performance issues read on.


I assume that you have some image gallery or magazine-style content area on your page

How about having this image area in a separate iframe? What you could do then is this:

  1. Have two iframes. Only one should be visible and active in time.
  2. Load images into first iframe. Track the size of loaded images. If exact size tracking is hard

    numberOfLoadedImages * averageImageSize

    might be a pretty good aproximation.

  3. As that number approaches some thresshold start preloading the currently visible content into second iframe.
  4. Flip the visibility of iframes so the second one becomes active.
  5. Clear the inner content of the first frame.
  6. Repeat the whole procedure as necessary.

I don't know for sure if this would work for you but I hope that WebKit engine on iPad clears the memory of frames independently.


EDIT: It turned out you're writing a game.

If it's a game I assume that you want to have many game objects on the screen at the same time and you won't be able to simply unload some parts of them. Here are some suggestions for that case:

  1. Don't use DOM for games: it's too memory-heavy. Fortunately, you're using canvas already.
  2. Sprite your images. Image sprites not only help reducing the number of requests. They also let you reduce the number of Image objects and keep the per-file overhead lower. Read about using sprites for canvas animations on IE blog.
  3. Optimize your images. There are several file size optimizers for images. SmushIt is one of them. Try it for your images. Pay attention to other techniques discussed in this great series by Stoyan Stefanov at YUI blog.
  4. Try vector graphics. SVG is awesome and canvg can draw it on top of canvas.
  5. Try simplifying your game world. Maybe some background objects don't need to be that detailed. Or maybe you can get away with fewer sprites for them. Or you can use image filters and masks for different objects of the same group. Like Dave Newton said iPad is a very constrained device and chances are you can get away with a relatively low-quality sprites.

These were all suggestions related to reduction of data you have to load. Some other suggestions that might work for you.

  1. Preload images that you will need and unload images that you no longer need. If your game has "levels" or "missions" load sprites needed only for current one.
  2. Try loading "popular" images first and download the remaining once in background. You can use separate <iframe> for that so your main game loop won't be interrupted by downloads. You can also use cross-frame messaging in order to coordinate your downloader frame.
  3. You can store the very most popular images in localStorage, Application Cache and WebSQL. They can provide you with 5 mb of storage each. That's 15 megs of persistent cache for you. Note that you can use typed arrays for localStorage and WebSQL. Also keep in mind that Application Cache is quite hard to work with.
  4. Try to package your game as a PhoneGap application. This way you can save your users from downloading a huge amount of data before playing the game. 200 megs as a single download just to open a page is way too much. Most people won't even bother to wait for that.

Other than that your initial suggestion to override cache with your images is actually valid. Just don't do it straight away. Explore the possibilities to reduce the download size for your game instead.

Upvotes: 2

Samuli Hakoniemi
Samuli Hakoniemi

Reputation: 19059

I managed to reduce the impact by setting all the images that aren't currently in the viewport to display:none. This was with background images though and I haven't tested over 100Mb of images, so can't say whether this truly helps. But definitely worth of trying.

Upvotes: 0

Related Questions