How to detect/handle low performance devices Javascript - javascript

I am working on a HTML canvas app that displays graphics to the screen. The graphics aren't important for the website, they just make things look pretty.
My problem is the app needs the cpu of the device to run at a certain speed or the frame rate becomes unacceptable.
Any modern phone/laptop can easily run the app, but of course not everyone has updated tech.
At that point I'd like to drop support for the device and stop rendering the animations because it will just do more harm than good.
This idea is pretty standard on the internet. For example if you want an image background for your site, but you don't want mobile phones to load the same large image as desktops then you just use some css queries to only serve the image to desktops.
This is how we can get new features pushed out while keeping backward compatibility.
However when it comes to detecting performance this isn't as easy of a task as it sounds. There's no way to get cpu specs with Javascript, and even if I could there's no way of telling what else the user is running on their machine.
This leaves me with 2 options, either run a small performance test before I start the canvas app. Or start the app and try to run a few frames and stop it if the frame rate is too low.
The problem is both of these options are pretty sketchy because the device may just have a "speed hiccup" at the start of the app, and so I shut down the animations for nothing.
Also if a user has a device that sits right on the border of the threshold sometimes the animations will load, and sometimes they won't which would probably be confusing.
Is there any "standard" on the internet to deal with this sort of problem? Would it be best to leave a footnote at the bottom of the site window when animations are turned off?
Or is it just something you have to accept when pushing the boundaries and dealing with performance?

Related

How to diagnose performance issues on my website

I've made a website that displays certain posts from Instagram, Facebook and Twitter. The website shows these posts in card form with certain animations and transitions. It works fine on the desktop but the goal is to run it on raspberry PIs and, when run from one of those, the animations and videos stutter. I want to reduce or eliminate the stutter and I'm considering several approaches:
web workers to offload some of the animation calculations to a separate CPU core
dynamic video compression on the server depending on what device will be playing the video
different animation methods
To figure out if any of these would help I'd want to first figure out what is actually causing the stutter but I don't know how to do this. I need a way to figure out what portion of the slowdown is due to what issue. Like, what's the impact of loading the images/videos, the impact of playing the video, of animating the elements etc. What is the best way of doing this?
Here is the working version of the site if that will help with the suggestions. Note that I'm not highly experienced with JS or programing in general and I was just starting out when I created this so it's far from optimal but now I need to figure out the best way to improve it.
This is probably a performance issue, but it could be something else. If you're using VNC Viewer or some other form of remote desktop, it could be because of that. If it's just wired to a monitor, though, it's most likely the fact that the CPU can't handle it. You could try to install a more lightweight browser, because Chromium can really take a toll on the CPU. Go to Chrome DevTools, and go to the performance tab. This should show you basically everything you need to know. I'm not sure if you're using CSS transitions or something else, so I can't really help you there. You could try NetSurf or Dillo as more lightweight browsers, though.

How can I check the speed and strength of site visitors computer?

I have made some pretty resource-intensive items on my new site's design, and I'm a bit concerned. While testing on different computers, I notice some simply cannot handle the computer generated art/animations nor 1080p video. This could be a problem.
So I'm already planning to test their Internet speed (or at least, that it's sufficient) using a "control file" and timing the response, but how can I (or what would be the best way) to do so for checking hardware?
So far I have:
Use a short 1080p video, test the time to download. Test start-finish time, see if there's lag.
Use a loading page with 2 gateways: one for regular, one for enhanced. Above the "door" to enhanced, have some heavy javascript animation - if it lags, they should click 'regular
'.
*loading page will likely be cookie-dependent overlay, don't want to send them to home page from search.
I'm not wild about either of those ideas, and I already strip the resource-intensive items for sizes under 700 or so. Kind of a "why should some suffer for others lacking" deal. Eventually all computers can handle it, but I can't be freezing their devices just to put on a good show.
Update
3 . Have an "awesome" page that records the destination URL, does some fast JS animation (totaling under 3 seconds), and says "testing device capabilities" then "proceed to site". This would automatically determine the best version and give them something cool to look at while it's testing.

How to control the framerate in KineticJS?

How can I control the rendering loop frame rate in KineticJS? The docs for Kinetic.Animation show a frame rate being passed to the render callback, and Kinetic.Tween seems to have no frame rate logic, but I don't see anyway to force, say, a 30fps when 60fps is possible.
Loads of context for the curious follows, but the question is that simple. If anyone reads on, other advice is welcome. If you already know the answer, don't waste your time reading on!
I'm developing a music app that combines some DOM-based GUI controls (current iteration using jQuery Mobile) and Canvas-based GUI controls (using KineticJS). The latter involve some animation. Because the animated elements are triggered by music playback, I'm using Kinetic.Tween to avoid the complexity of remembering how long a given note has been playing (which Kinetic.Animation would require doing).
This approach works great at 60fps in Chrome (on a fast machine) but is just slow enough on iOS 6.1 Safari (iPad 2) that manipulating controls while animations are happening gets a little janky. I'm not using WebGL (unless KineticJS or Chrome does this by default for canvas?), and that's not an option when I package for native UIWebView.
As I'm getting beyond prototype into wanting to make more committed tech decisions, I see the following options, in order of perceived goodness:
Figure out how to cap the frame rate. Because my animations heavily use alpha fades but do not involve motion, I believe I could get away with 20-30fps and look fine. Could also scale this up on faster devices.
Don't respond immediately to touch inputs, but add them to a queue which I poll at a constant interval and only use the freshest for things like touchmove. This has no impact on my non-interactive animated elements, but tackles the problem from the other direction, trying to reduce the load of user interaction. This would require making Kinetic controls static and manually tracking touch coordinates (not terrible effort if it actually helped).
Rewrite DOM-based GUI to canvas-based (KineticJS); rewrite WebAudio-based engine to HTML5 audio; leverage CocoonJS or Ejecta for GPU-acceleration. This means having to hand-code stuff like file choosers and nav menus and such (bad). Losing WebAudio is pretty serious as it eliminates features like DSP effects and very fine-grained, low-latency timing (which is working just fine on an iPad 2).
Rewrite the app to separate DOM based GUI and WebAudio from Canvas-based elements, leverage CocoonJS. I'm not sure if/how well this works out, but the fact that CocoonJS passes JavaScript code as strings between the 2 components makes me very skittish about how solid this idea is. It's probably doable, but best case I'm very tied to CocoonJS moving forwards. I don't like architecting this way, but maybe it's not as bad as it sounds?
Make animations less juicy. This is least good not because of its design impact but because, as it is, I'm only animating ~20 simple shapes at any time in my central view component, however they include transparency and span an area ~1000x300. Other components like sliders are similarly bare-bones. In other words, it's not very juicy right now.
Overcome severe allergy to Objective-C; forget about the browser, Android, and that other mobile OS. Have a fast app that performs natively and has shiny Apple-approved widgets. My biggest problem with this approach is not wanting to be stuck in Objective-C reality for years, skillset-wise. I just don't like it.
Buy an iPad 3 or later. Since I already am pretending Android doesn't exist (I don't have any devices to test), why not pretend no one still has iPad 2? I think this is passing the buck -- if I can get acceptable performance on iPad 2, I will feel confident about the app's performance as I add more features.
I may be overlooking options or otherwise naive about how to tackle this. Some would say what I'm trying to build is just silly. But it's working pretty well just not ready for prime time on the iPad 2.
Yes, you can control the Kinetic.Animation framerate
The Kinetic.Animation sends in a frame object which has a frame.time property.
That .time is a running timer that you can use to throttle your animation speed.
Here's an example that throttles the Kinetic.Animation: http://jsfiddle.net/m1erickson/Hn3cC/
var lastTime;
var frameDelay=1000;
var loop = new Kinetic.Animation(function(frame) {
var time = frame.time
if(!lastTime){lastTime=time;}
var elapsed = time-lastTime;
if(elapsed>=frameDelay){
// frameDelay has expired, so animate stuff now
// set lastTime for the next loop
lastTime=time;
}
}, layer);
loop.start();
Working from #markE's suggestions, I tried a few things and found a solution. It's ultimately not rocket science, but sharing what I figured out:
First, tried the hack of doubling Tween durations and targets, using a timer to stop them at 50%. This kinda sorta worked but was hard to get to look good and was pretty error prone in coding bogus targets like negative opacity or height or whatnot.
Second, having read the source to Tween and looked at docs again for Animation, decided I could locally use Animation instances instead of Tween instances, and allow the closure scope to hang onto the relevant note properties. Eventually got this working smoothly and finally realized a big Duh! which is that throttling the frame rate of several independently animating things does not in any way throttle the overall frame rate.
Lastly, decided to give my component a render() method that calls itself in a loop with requestAnimationFrame, exits immediately if called before my clamp time, and inside render() I update all objects in the Kinetic canvas and call layer.drawScene(). Because there is now only one animation, this drops frame rate to whatever I need and the app is fast on iPad 2 (looks exactly the same to my eyes too).
So Kinetic is still helping for its higher level canvas API, and so far my other control widgets are still easy code using Kinetic to handle user input and dragging, now performing much better as the big beast component is not eating up the CPU.
The short answer to my original question is that no, you can't lock the overall frame rate for very complex animations, but as Mark said, you can for anything that fits in a single Animation instance.
Note that I could have still used Animation without giving it a layer or explicitly calling any draw() methods, but since I'd still have to write all the logic to determine individual element's current visual state, there was no gain to doing this. What would be very useful would be if Tween could accept a parameter to not automatically render. This would simplify code like mine, as I could shorthand the animation on individual objects but still choose when to actually do the heavy lifting of rendering everything. Seeing how much this whole exercise gained in performance on the iPad 2, might be worth adding this option to the framework.

Running a quick Javascript benchmark on first load

What I would like to do is run a simple and fast Javascript benchmark when a user first access my web application to detect his computer's capacity to animate elements. I remember a teacher did this in college to adapt the frame rate of his game depending on the user's machine.
Is it something that could be done without sacrificing too much user resources? Maybe a few seconds after the page is loaded? And if the results are not good, we just disable some or all animations for this user.
To answer the questions that you asked in your post:
1) It is possible to run a JavaScript benchmark when a person first loads your site that will test their capacity for CSS/JavaScript animation speeds, but it will sacrifice several resources. You have to consider the people who will be accessing your site. If they're going to be accessing your site via a mobile device, the last thing you want to do is bring their device to a standstill and either freeze their browser or bump other apps out of memory. You don't want either a desktop or mobile user to think that the site is unresponsive.
2) One of the issues with waiting a few seconds after the page has loaded is that, depending on what you want to do with the site, people will start to try to scroll through your content. If they start to scroll and realize that the site is "stuttering", they may think that something is wrong with their device.
Another caveat is that if you want the smoothest animations possible, you may end up using requestAnimationFrame (see https://hacks.mozilla.org/2011/08/animating-with-javascript-from-setinterval-to-requestanimationframe/). If somebody loads your site and then clicks away from it to a different tab while your test is running, browsers have adopted the practice of reducing the framerate in inactive tabs in favor of those in the active tab. Testing based on this (incorrect) framerate capability will result in parts of your site being disabled for people who are perfectly capable of running your site with all of the animations intact, so that's something you may need to take into account.
In some tests that I ran a couple of months ago, the CSS3 version of an animation was almost always smoother than the JavaScript version of an animation. However, there are now jQuery libraries that bridge this gap by using CSS3 animations when possible, such as jQuery Transit (http://ricostacruz.com/jquery.transit/).

Flash causing jerky javascript animations

I'm developing a site which has a flash background playing a small video loop scaled to fill the whole background. Over the top I have a number of HTML elements which are animated using javascript. The problem I am having is that (predominantly in FF, but also in others to a lesser degree) the flash seems to be causing my javascript animations to run rather jerky, and in some cases missing the animation altogether and just jumping to the end state.
Does anybody have any thoughts on how to make the 2 work together nicely?
Many thanks
Matt
You'll notice the same effect on BBC Iplayer - if you've played a few videos, then use the left and right scroller. The javascript animation is no longer smooth.
The is more noticeable in FF.
Chrome creates an entirely separate process for the flash, and therefore smoother, Safari is quite lightweight therefore smoother at times.
Bit of a bugger really - the only thing I can suggest is ensure your swf is optimised for CPU - if it contains lots of code, ensure you doing good memory management.
I had the same trouble once and I targeted FP10 - this offset a lot of visual work off the CPU (therefore the current process in the browser) and gave it to the GPU.
--
Aside from this, you're pretty much at the mercy of how powerful the clients machine is.
Additional for my answer above:
Thanks Glycerine. Do you think there would be any performance improvements if it was compressed into an older format? Or even just a SWF? There is no audio, so it's just an animated background really. – - Matt Brailsford
I think a newer format would be better - if you can do FP10, then again, you'll be able to utilise the user GPU, if your working in CS3, best to go for FP9.5.
Ensure your stage objects are cached for bitmap if your using large vectors
http://www.adobe.com/devnet/flash/articles/bitmap_caching_print.html
This ensures any heavy animation (even animation we regard as light) will run smoother because there turned into pixel data as opposed to complicated vector information. Its a small fix but it may work.
Try and target the AS3 engine as well. Even if your not using code. I keep saying it runs better than the as2, as1 engine with arguments from people but I'm sure you'll find your favourite camp.
If you have very large images scaled down, use a smaller form factor by photoshoping then to a smaller size. This will not only improve rendering speeds, but also swf file size.
Try those.

Categories