erik-krogh / SudoSlider

The most versatile jQuery content slider
36 stars 24 forks source link

Dragging slides on Android has a significant lag #64

Closed codener closed 6 years ago

codener commented 6 years ago

When dragging slides on an Android phone, there is a serious lag. I did not observe this behaviour on an iPhone SE.

How to reproduce

  1. Open any SudoSlider demo (http://webbies.dk/SudoSlider/demos.html#touch) on an Android device (e.g. a moto g5 with Android 7 and Google Chrome)
  2. Drag a slide a little bit
  3. Let go
  4. Observe a little lag before the slide starts moving to its final position

In the demos, the lag is (negligibly) small. In a production environment with six four-slide sliders however, the lag is more than a second.

I haven't figured out what causes this. Specifically the difference between iOS and Android bugs me...

Have you seen this before?

webbiesdk commented 6 years ago

I haven't noticed it before, but I tried it out on my phone (Oneplus 6). I only observe a very tiny amount of lag (don't have an iPhone to compare against). It is only barely noticeable to me (and I'm the kind of guy that gets annoyed by the low FPS in cinema movies).

I think it is related to css-transitions. When you drag-and-drop a slider the following happens:

I tried to disable css-transitions (option: useCSS:false), and it seems the tiny lag disappeared (but the entire animation became jittery, there is a reason I implemented css transitions). When css-transitions are disabled, the slider essentially moves the same way both while dragging and after the finger is lifted.

So I have some idea as to what is happening, but little idea on how to fix it.

I'll look at the source later today, and see if there is some delay I can remove.

codener commented 6 years ago

Thanks for your thorough reply! Could you have a look at https://www.audi-mediacenter.com/en? This is where we first noticed it. Sometimes it works perfectly, but e.g. after trying all sliders and scrolling back up to the first, it really gets stuck.

I know that virtually anything could be causing this, that's why I sent one of your demo pages first (where I saw a quite noticeable lag), but on Audi MediaCenter the slider sometimes gets stuck for 4 seconds.

Random thoughts – what do you think?

webbiesdk commented 6 years ago

Since you say it sometimes gets stuck for 4 seconds, I think it must be caused by css-transitions. I tried your website on my Android phone, but I didn't notice any more lag than on the demo page. (Which might be because my phone being the fastest Android phone on the market...) I also notice more lag on your page when opening on my Android phone.

As I said before, you can try at set useCSS to false. But doing that will cause most animations to be more jittery.

could it be related to slider size (i.e. pixels)?

Yes, mostly the amount of pixels in the images. (I just opened one of your images, it was 2400X1714 pixels, which is massive) Making the images smaller should help a lot, but I don't think the problem will completely disappear.

could it be related to slider content size (bytes, i.e. large images)?

I highly doubt it, when an image is shown it doesn't matter much how big the file was, it matters how many pixels there are in the image after the browser has opened the file.

could it be related to many slider instances in one page?

Only if the phone runs out of memory from there being too many images on the page (all slides are in memory all the time).

codener commented 6 years ago

Did you open the images on a desktop computer? Your smartphone should get a ~500px width image, depending on its resolution.

I will try disabling useCSS and investigate further. Thanks for investigating! I'll keep you updated on my findings.

webbiesdk commented 6 years ago

I've been looking at bit on how other sliders do it, e.g: http://idangero.us/swiper/demos/300-thumbs-gallery.html

They use a simpler transition, where the speed after the animation speed after the finger has been lifted does not depend on the speed with which your finger moved. But that is also the only difference, everything else is exactly the same as SudoSlider.

They still have a tiny bit of lag (I think) between the finger being lifted and the transition beginning.

Can you see how well their slider performs on your devices? I might be possible for me to use that simpler transition if it turns out to perform better.

codener commented 6 years ago

Hm, apparently their server has a hard time delivering the page. The demo is loading only very few images. I've tried on the same Android phone: I have a little lag when starting to drag a slide, feels as if it were stuck a little bit. When letting go, it's really smooth (I am not the kind of guy that notices low cinema FPS).

However, we've found that the introduction of multiple sudo sliders introduced the lag. Chrome Performance analysis showed a strange idle time of 1,6s(!) after letting go of a dragged slide. Will investigate further and report.

webbiesdk commented 6 years ago

Nice.

I didn't expect multiple sliders to make a difference, that they do gives me something to look for.

webbiesdk commented 6 years ago

Ok. I got something.

Turns out that having a lot of images that has the style: position:relative causes the lag (that the container is display:block seems to also do something?).

Anycase, I did a thing, it's not completely done yet, but you can try it out. What I do is that when the slider is not animating I hide all the slides that are invisible anyway, and reset the style to how it would be if I hadn't initialized SudoSlider. Since all non-visible slides are hidden, resetting the style shouldn't break things.

Then when a animation begins (or a user starts dragging the slider), I quickly re-initialize the style and make all slides visible (because all my animation code heavily relies on position:relative).

This seems to work. But I only got it to work for the simplest case for now.

You can see the fixed version here: http://webbies.dk/assets/files/SudoSlider/touch/demos/audi.html?slides=100

And the unfixed version here: http://webbies.dk/assets/files/SudoSlider/touch/demos/audi_old.html?slides=100

Change the slides=100 to change how many sliders the page should contain. On my phone I set it to 500 to get an annoying amount of lag.

You can try out the work-in-progress script if you want to: https://gist.github.com/webbiesdk/912247d8a595f1cb5ef239165d20e910 (The new code is the hideExcess and showAll functions).

webbiesdk commented 6 years ago

Shit, wrong links. Will fix tomorrow.

webbiesdk commented 6 years ago

I've experimented some more.

I don't think it will get any better, unless we find some fix other than modifying the position and display style of the slides.

This is the current version of the script: https://gist.github.com/webbiesdk/c51776faf23738d792f42a4acded085d

Some of it will likely be released in a later version, but I'm not even sure of that.

codener commented 6 years ago

Awesome, thanks for putting so much effort into this!

I will try and compare the fixed/unfixed versions and report back. (Don't have an Android phone at hand today.)

codener commented 6 years ago

I did a few tests from different angles:

Device

I have compared Chrome with Firefox for the original www.audi-mediacenter.com, on an Honor phone with Android 8. Chrome lags around several seconds. The lag is smaller on Firefox.

Interestingly, on a recent Sony Xperia, there is (almost) no lag in neither browser.

Page content

Also, I removed all sliders but the first (leaving the content in place). This did not change anything about the lag.

Not rendering images (thus reducing the "data rendering weight" of the page) didn't help anything, nor did disabling all kinds of fancy JS used for embellishments throughout the page.

A slider alone on the page however, had a much smaller lag.

Your workaround

The "disable inactive sliders" workaround improves slider performance a lot. It seems it restores the "single slider on a page" behavior. In other words: it does the best improvement I could find.

Conclusion

I could not identify a culprit in our application, neither JS nor CSS. A Chrome performance analysis shows the Android device is idling just about 2s during slide transition (i.e. no JS time, no painting, no compositing etc). I could not figure how to prevent or fix this.

So, could you please incorporate this workaround in the slider? Apparently it is only required for complex slider setups (and only for weaker Android devices with Google Chrome), so maybe it could only be activated with a config option.

If you need any support, let me know.

webbiesdk commented 6 years ago

Thanks for the extensive testing.

I only tested on a Oneplus 6, which is just about the fastest Android phone on the market, so you testing on older devices is helpful. (Btw. I also tested www.audi-mediacenter.com on a 6 year old iPad, and all the sliders were very laggy).

Your conclusion seems to be the same as mine, as there seems no real cause for the lag. My best bet is that the browser needs to do some calculation on all images that have been non-default positioned using CSS, before it can perform the transition, and that this causes the lag.

I will implement my current work as an option (might take a week before I do it). for now you can just use my work in progress version: https://gist.github.com/webbiesdk/c51776faf23738d792f42a4acded085d That version has all the performance fixes enabled,

codener commented 6 years ago

Yes, that's about my conclusion. Good that you tested it on an old iOS device, that makes it more likely that it's a performance thing. On a 2yo iPhone SE everything is smoothest, so I had thought it might be Android/Chrome related.

As the ratio of urgency to effort is currently too bad :wink: I'll wait for the updated release.

Thanks for your help and quick replies! :bowing_man:

webbiesdk commented 6 years ago

About the iOS testing. I only experience that all slider animations were laggy, I didn't experience multi-second lag when the finger was lifted (as you experienced on older Android devices).

Anyway, I just released 3.5.0, and I hope it works. You just need to add the option performanceMode:2.

Btw. If you visited the SudoSlider webpage in the last few days (not the GitHub page), then I hope you did it from an up-to-date browser. My website got hacked by this thing: https://forums.modx.com/thread/104079/urgent-active-attacks-on-modx-revolution-sites-below-revolution-2-6-5

codener commented 6 years ago

Thanks for the update! It works as expected, drastically improving slider performance on slow/old Android devices. (Tiny lag still there, but that's ok.)

As for the website hack, I have an up-to-date browser, yes, but I do not understand how I'd be affected by that vulnerability. Isn't it a server-side thing? Or have you found malicious Javascript? Or did you just want to give me a general hint?

webbiesdk commented 6 years ago

Good to hear that it worked as expected.

And yes that is a server-side hack. But it has the consequence that I got no idea what my website was showing since at least Friday evening. So yes, it was just a general hint, I actually don't even know if there was a malicious JavaScript payload. I fixed it yesterday evening.