Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: Improve collection-repeat image performance on iOS #3194

Closed
ajoslin opened this issue Feb 27, 2015 · 34 comments
Closed

perf: Improve collection-repeat image performance on iOS #3194

ajoslin opened this issue Feb 27, 2015 · 34 comments
Milestone

Comments

@ajoslin
Copy link
Contributor

ajoslin commented Feb 27, 2015

Problems:

  • Setting an un-cached url to an img src gives a 50-200ms freeze on an iPhone 6.
  • iOS UIWebView doesn't properly cache remote image urls. Even after setting once to a url, setting again to the same url will cause a noticeable freeze.

Solutions:

  • Use a web worker to fetch image srcs, convert them to base 64, and give them back as a data-uri.
    • This works.. almost. Once an image has been set to a data-uri once, the WebView does properly cache the uri and reloads it instantly when it's set the next time.

The last solution needed is a way to cache the data uri into the webview beforehand. This will require some experimentation, but it's doable.

@ajoslin ajoslin added this to the 1.0.0-rc1 milestone Feb 27, 2015
@ajoslin ajoslin self-assigned this Feb 27, 2015
@wedgybo
Copy link

wedgybo commented Mar 3, 2015

Just wanted to leave a link to something I looked at previously. It might be worth benchmarking against your web worker code to see how it compares. https://github.com/mallzee/cordova-collection-repeat-image-plugin

@felquis
Copy link

felquis commented Mar 3, 2015

I tried to create something like this in the past, the main idea was to create a directive to use in wherever I want to use with src or ng-src like:

<img ng-src="my-awesome-pic.png" ion-utils-cache-base64>

And store the base64 in a variable in a some factory or something like that. Just sharing my thoughts on this.

@saniyusuf
Copy link
Contributor

HI @ajoslin I have a component that does something similar that caches the data URI base64string of an image for Ionic apps. I have done that part and are about to integrate the web worker .

@felquis exactly what you are explaining is what I have worked on with some success.

https://github.com/saniyusuf/imagenie

@ajoslin
Copy link
Contributor Author

ajoslin commented Mar 3, 2015

Thanks all!

I also tried the ng-src route. It just wasn't a convincing enough improvement for us to make it part of the framework yet.

I'll look at everything you guys have linked. Thanks a lot. The Cordova plugin route is especially interesting...

@saniyusuf
Copy link
Contributor

Any update on this?

@ajoslin
Copy link
Contributor Author

ajoslin commented Mar 9, 2015

We've been at ng-conf and only just returned. I'll be looking into it this week.

@saniyusuf
Copy link
Contributor

HI Andrew,
I am really keen to be involved with the web worker. I have put my own
implementation on hold to see what we come up with.

On 9 March 2015 at 15:19, Andrew Joslin notifications@github.com wrote:

We've been at ng-conf and only just returned. I'll be looking into it this
week.

Reply to this email directly or view it on GitHub
#3194 (comment).

Kind Regards
[image: photo]
Sani Yusuf
Co-Founder / CTO, Slapic
http://github.com/saniyusuf
http://stackoverflow.com/users/1714088/sani-yusuf
http://about.me/saniyusuf
http://linkedin.com/in/saniyusuf https://twitter.com/saniyusuf
Get a signature like this:
http://ws-stats.appspot.com/r?rdata=eyJydXJsIjogImh0dHA6Ly93d3cud2lzZXN0YW1wLmNvbS8/dXRtX3NvdXJjZT1leHRlbnNpb24mdXRtX21lZGl1bT1lbWFpbCZ1dG1fY2FtcGFpZ249cHJvbW9fNDUiLCAiZSI6ICJwcm9tb180NV9jbGljayJ9
Click
here!
http://ws-stats.appspot.com/r?rdata=eyJydXJsIjogImh0dHA6Ly93d3cud2lzZXN0YW1wLmNvbS8/dXRtX3NvdXJjZT1leHRlbnNpb24mdXRtX21lZGl1bT1lbWFpbCZ1dG1fY2FtcGFpZ249cHJvbW9fNDUiLCAiZSI6ICJwcm9tb180NV9jbGljayJ9

@ajoslin
Copy link
Contributor Author

ajoslin commented Mar 10, 2015

Working on this today.

@saniyusuf
Copy link
Contributor

Any idea how you intend to do the conversion in the worker since worker
does not have the document object

@ajoslin
Copy link
Contributor Author

ajoslin commented Mar 10, 2015

We don't need the document object. I already know how to convert the worker to base64 (I'll have code up later today).

The problem is caching the image before it hits the visible DOM.

@ryanricig
Copy link

Hey - also anxiously awaiting this one, we've got an infinite list of images (like Facebook timeline) of unknown heights (until the images load). Currently we've got an ng-repeat being used but we are seeing some memory issues. So we have switched to the new collection-repeat, but as you note, there is a choppy stop-n-go type nature to the scrolling. Excited to see what you guys come up with.

@felquis
Copy link

felquis commented Mar 17, 2015

What if we use a plugin (like file-transfer) to literally download the image, and use it as a local image... I think it probably load faster than always reaching an external URL.

@wedgybo
Copy link

wedgybo commented Mar 17, 2015

There are performance gains to be had doing that, but they don't make a huge difference. When you start getting crazy with images, even applying a base64 string version of it still stalls the browser because it's painting on the main thread. Even more so if the image has to be scaled to fit the space. The main thing that's going to help this I believe it the native scrolling. Once that becomes standard there will be a lot more time on the main thread for stuff to happen. Then maybe offloading some preloading to service workers or something to keep things smooth.

Another stop gap solution for offloading the scaling is to run an image proxy which is cached by something like cloudfront. We run a simple node server on heroku which will download an image, scale it to the size requested, and serve it with a cache TTL of a few days. That way the majority of the load is handled by the cache for the majority of our users. Then we just created a directive to augment the image tag to calculate the space that needed to be filled by the image and redirected to our image proxy.

@okonon
Copy link

okonon commented Mar 17, 2015

@AceLondon
Copy link

Have you seen this web worker wrapped in an angular service? Looks promising. https://github.com/FredrikSandell/angular-workers

@perrygovier perrygovier modified the milestones: 1.0.0-rc2, 1.0.0-rc1 Mar 20, 2015
@Fayozjon
Copy link

softBarbarian

http://goohoo.net/bitcoin-forex4you

18.03.2015, 01:50, "softBarbarian" notifications@github.com:Take a look at

—Reply to this email directly or .

@perrygovier perrygovier modified the milestones: 1.0.0-rc2, 1.0.0-rc3 Mar 30, 2015
@adamdbradley adamdbradley modified the milestones: 1.0.0-rc3, 1.0.0-rc4 Apr 13, 2015
@wootapa
Copy link

wootapa commented Apr 30, 2015

Any update on this?

@perrygovier
Copy link
Contributor

Andrew got the web worker to process image data and feed it back to the main thread as base64 data working, but it didn't result in a significant performance boost. It was a great idea, one we'll probably leverage in different ways for Ionic v2, but it didn't help in this case.

Feel free to take a look at Andrew's PR if you want to play around with it, but I don't think we'll be adding this to v1 of Ionic unless we come up with ideas of how to improve the performance further.

@onigetoc
Copy link

I see many APP who hide the image when not in view and they reappear when you scroll.
Do you think thant just make in visibility hidden when out of view can change something in performance?

@salqadri
Copy link

I am seeing the same issue. I try to display images in an ion-scroll and they don't show; I then move the scroll slightly and it shows up. When I pop the view and push into it again the images again don't show even though they were loaded up and showing earlier. Annoyed.
EDIT: Tried the 'collection-repeat' technique and it works amazingly well and solves my issue. Thanks!

@revolunet
Copy link

@salqadri : you mean @wedgybo cordova plugin ?

@roblav96
Copy link

take a look at what the team at angular material did to remedy this issue:

angular/material@d68b4f6f

@louisdoe
Copy link

louisdoe commented Dec 1, 2015

Hi everyone, is this issue still in ionic version 1.1.0 ?
I have a long list in my app using collection-repeat, I am a newbie, what should I do to make perf ?

Thanks

@m52go
Copy link

m52go commented Dec 8, 2015

This issue isn't limited to collection-repeat. The main view on my app is a collection of cards, each with their own background-image set:

<div class="image" style="background-image:url('{{ card.cover_picture }}');">

Just having that background image set slows the app to a crawl (on iOS) whenever navigating to or from that template. I'm using ng-repeat because I only load 15-60 cards into the DOM at any time, but the exact same problem persists with raw HTML (i.e., no ng-repeat or collection-repeat).

The delay seems to increase with the number of cards in the DOM, but it's even perceptible with just 2-3 cards, so I can't work around the issue by limiting the number of elements in the DOM.

Taking that background-image CSS out makes everything normal again. This is a huge problem for me.

EDIT: apparently ng-src on an img tag is supposed to cache but that's not helping.

EDIT 2: after a week of trying everything I could possibly imagine, the delay I was seeing was occurring because the elements in which the images are placed are absolutely positioned. No idea why, but that's what was causing the delay. Sorry. This message can be disregarded as it's no longer relevant to this thread.

@tgensol
Copy link

tgensol commented Mar 16, 2016

I created a directive like this :

<div image="{{item.image}}" set-image></div>

directive('setImage', function () {
  return {
    restrict: 'A',
    link: function (scope, elem, attrs) {
      attrs.$observe('image', function (val) {
        if (val) {
          elem.css('background', 'url("' + val + '") #eee no-repeat center center');
          elem.css('background-size', 'cover');
        }
        else{
          elem.css('background', '#eee');
        }
      });
    }
  };
})

And the performance issue is no longer here. Hope this help

@onigetoc
Copy link

Do blob image do a difference rather than base64?
I'm creating a Chrome app and it do not accept external image. so i had to create a directive to transform image to blob or image to base64.
https://gist.github.com/onigetoc/928f11e4127f81434b46

@ihuseynoff
Copy link

I have noticed that it was solved for ionic 2. Is there any improvement for ionic 1?

@khkmalki
Copy link

Up Up

Anything here ?

@Rakonda
Copy link

Rakonda commented Nov 12, 2016

Interesting in any update

@tgensol
Copy link

tgensol commented Nov 12, 2016

My directive is working very fine on my mobile app, did you try it ?

@pablomaurer
Copy link

same as @tgensol but bit modified for my needs

<img ng-src="{{imagePath}}" collection-image image="{{imagePath}}">
angular.module('starter').directive('collectionImage', function () {
    return {
        restrict: 'A',
        link: function (scope, ele, attrs) {
            attrs.$observe('image', function (val) {
                ele.src = val;
            });
        }
    };
});

@ihuseynoff
Copy link

None of the directives provide smooth performance as ionic 2 provide.

@tgensol
Copy link

tgensol commented Nov 15, 2016

Sure, but you cannot compare angularJS1 to angularjs 2 I guess

@khkmalki
Copy link

Hi, I have notice there is a problem with scrolling in general especially on iPhone 5s wither it is Hybrid or Native App. You have to handle this on your own. Some remove image temporarily when it is not on the current view, others divide it into pages instead of scrolling 1 page. You can write an algorithm that handle massive numbers of elements, then sell it, I mean share it.

Sent from my iPhone

On Nov 15, 2016, at 5:53 AM, Thibaut notifications@github.com wrote:

Sure, but you cannot compare angularJS1 to angularjs 2 I guess


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Sep 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests