I am testing performance in my JavaScript application, a game using canvas. One problem I have is major fluctuations with FPS: going from 60 to 2 in ms.
As you can see, there are major spikes. It is not due to painting, scripting, rendering, or loading. I think it is because requestAnimationFrame doesn't assign a set FPS rate and it might be too flexible? Should I use setTimeout? Is it usually more reliable in these cases because it forces the application to run in only one set FPS rate?
Performance is always about specifics. Without more information on your app, (e.g. the specific code that renders your app ). It is hard to say how you should structure your code.
Generally, you should always use requestAnimationFrame. Especially for rendering.
Optionally store the delta time and multiply your animation attributes by that delta. This will create a smooth animation when the frame rate is not consistent.
I've also found random frame rate changes are usually related to garbage collection. Perhaps do some memory profiling to find if there are places you can avoid recreating objects each frame.
requestAnimationFrame is superior to setTimeout in nearly every way. It won't run as a background tab. It saves battery. It gives the browser more information about the type of app you are developing, and this lets the given browser make many safe performance increasing assumptions.
I highly recommend watching this talk by Nat Duca on browser performance.
Related
I am trying to understand why it's a hard task for browsers to fully render the DOM many time per second, like game-engines do for their canvas. Games engines can perform many many calculation each frame, calculating light, shadows, physics etc`, and still keep a seamless frame rate.
Why browsers can't do the same, allowing full re-rendering of the DOM many times per second seamlessly?
I understand that rendering a DOM and rendering a Game scene are two completely different tasks, but I don't understand why the later is so much harder in terms of performance.
Please try to focus on specific aspects of rendering a DOM, and explain why games-engines don't face the same problems. For example- "browsers need to parse the HTML, while all the code of the game is pre-compiled and ready to run".
EDIT: I edited my question because it was marked as opinionated. I am not asking for opinions here, only facts. I am asking why browsers can't fully re-render the DOM 60 frames per second like game-engines render their canvas. I understand that browsers faces a more difficult task, but I don't understand why exactly. Please stick with informative answers only, and avoid opinions.
Games are programs written to do operations specific to themselves - they are written in low level languages asm/c/c++ or at least languages that have access to machine level operations. When it comes to graphics, games are able to push programs into the graphics cards for rendering: drawing vectors and colouring / rasterization
https://en.wikipedia.org/wiki/OpenGL
https://en.wikipedia.org/wiki/Rasterisation#:~:text=Rasterisation%20(or%20rasterization)%20is%20the,which%20was%20represented%20via%20shapes)
they also have optimised memory, cpu usage, and IO.
Browsers on the other hand are applications, that have many requirements.
Primarily designed to render HTML documents, via the creation of objects which represent the html elements. Browsers have got a more complex job, as they support multiple version of the dom and document types (DTD), and associated security required by each DTD.
https://en.wikipedia.org/wiki/Document_type_declaration#:~:text=A%20document%20type%20declaration%2C%20or,of%20HTML%202.0%20%2D%204.0).
and have to support rending a very generic set of documents - one page is not the same as another. Have to have libraries for IO, CSS parsing, image parsing (JPEG, PNG, BMP etc.....) and movie players and associated codecs, audio players and their codecs, and web cams support. Additionally they support the JavaScript code environment (not just the language - but IO and event handling) - also have historic support for COM, Java Applets.
This makes them very versatile tools, but heavy weighted - they carry a lot of baggage.
The graphic aspects can never be quite as performant as a dedicated program in this aspect, as the API they provide for such operations is always running at a higher level.
Even the Canvas API (as the name suggests) is a layer of abstraction above the lower level rendering libraries. and each layer of abstraction adds a performance hit.
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
For a better graphics performance there is now a new standard available in browsers call webGL - though this is still an API, and runs in a sandbox - so still will not be as performant as dedicated code
https://en.wikipedia.org/wiki/WebGL
Even games using game engines: Unity, Unreal will be accessing graphical features, CPU, memory, and IO in much more a dedicated fashion then browsers would - as the game engines themselves provide dedicated rendering and rasterization functions, that the developer can use in their games for optimised graphical features.. Browser cant as they have to cover many generic cases, but not specific requirements.
https://docs.unrealengine.com/en-US/Engine/index.html
https://learn.unity.com/tutorial/procedural-sky-19-1
First of all, games on the Web don't use the DOM much. They use the faster Canvas API. The DOM is made for changing content on a document (that's what the D in DOM stands for), so it is a really bad fit for games.
How is it possible that my crappy phone can run Call Of Duty seamlessly, but it's so hard to write a big webpage that will run smoothly on it?
I never had performance problems with the DOM. Of course, if you update the whole <body> with a single .innerHTML assignment 60 times a second, I wouldn't be surprised if the performance is bad, because the browser needs to:
Parse the HTML and construct the DOM tree;
Apply styles and calculate the position of each element;
Render the elements.
Each of those steps is a lot of work for the CPU, and the process is mostly single-threaded in most browsers.
You can improve the performance by:
Never using .innerHTML. .innerHTML makes the browser transform HTML into a DOM tree and vice-versa. Use document.createElement() and .appendNode().
Avoid changing the DOM. Change only the CSS styles, if possible.
Generally , it's depend about the game . the most powerful games are developed in C++ or C engine , so they are directly in touch with the memory and use the full power of processor.
Instead to web pages based on DOM , they are wrote it by interpreted language like JavaScript. Also , the problem can be from the server if the webpage it's deployed not correctly or in a bad slow server .
So I understand that in order to maintain the standard 60 frames per second when running animations in a web browser, we only get around 16ms per frame to perform any task we want to. The browser has to typically go through all the steps of the rendering pipeline to render each frame:
However, experts like Paul Lewis say that we realistically have only 10ms every frame to complete our tasks as browser has some 'overheads' and 'housekeeping' to do for every frame. I would like to know what these 'overheads' and 'housekeeping' tasks actually are?
"Overheads" vary per browser, and most don't occur on "every frame," but it all adds up, and overhead tasks performed either by your browser or by common client-side third-party code like Google Analytics also takes up valuable milliseconds. Common overhead tasks include:
Garbage collection
Listening for and handling often-repeated events such as scroll, mousemove, and some touch events (e.g. if you have analytics libs that generate heatmaps, that software may be tracking every mouse operation and touch operation)
Animations on your page (CSS ones or JavaScript-manages ones) which are "overhead" as far as the operation of your page are concerned
Third-party (or your own) code which does its thing only after certain conditions are met (e.g. lazy-loading of images, where images are loaded (and painted and composited) only when onscreen or close to being onscreen
Ads served by ad networks
Your own asynchronous code (triggered by setTimeout(), setInterval(), event-handlers, etc. etc. etc.) and that of any third-party libs which executes at some point, and when it does, eats into your 16ms (obviously there's a lot of overlap between this and the previous point)
Ad blockers and similar plugins (these run on a different thread, but interact with your thread, e.g., whenever DOM manipulation is necessary or any other cross-thread communication)
Loading of streaming media (which often consists of many network requests behind the scenes), which can include even relatively short, static videos
The overhead of running GIF animations or video (yours or UGC) - which is separate from the previous item, which concerns just the network interaction)
The repainting that needs to occur whenever the user scrolls or jumps to another part of your page (independent of any listeners for scroll, resize, etc.)
The potential complete redrawing of the DOM if some types of elements are added, removed, or resized, by you or by the user
Handling XHR or Iframe server responses or other data incoming from the network (like websockets traffic)
Tracking pixels (loading them, handling their demands of valuable JavaScript engine time); note that large sites often have a dozen or two tracking pixels of different types on them, and all it takes is one poorly written one to make huge demands on your browser's limited resources)
logic which attempts to anticipate what will happen next, and performing the optimizations involved
Heavy CPU usage by other applications running in your OS (or other pages running in other tabs in your browser) which take resources away from the JavaScript engine, rendering engine, etc.
Event-loop overhead - the JavaScript event loop is an elegant way of handling single-threaded code, but there's overhead involved in operating it
All of the above (a not-even-close-to-comprehensive list) would be considered "overhead" to whatever specific stuff you're trying to accomplish within 10ms or 16 ms or whatever.
Also note that some devices are just not capable of maintaining 60fps in-browser or anywhere; a slow CPU, lack of sufficient memory or persistent storace, etc., can slow all applications down, browsers included.
Maybe you're looking for something more specific, not sure - but I think I know the Paul Lewis thing you mention (where he talks about 10ms vs 16.66ms, etc.) and I'm not sure exactly what overhead he's talking about - but if, for example, you're trying to make one animation on a webpage run at 60fps, then all of the above would be "overhead" compared to your specific task of optimizing your animataion.
Hope this helps!
According to https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame referring to requestAnimationFrame
The number of callbacks is usually 60 times per second, but will generally match the display refresh rate
I've not managed to find a system that runs at something other than 60fps. If the Javascript is busy, then I can certainly get it to be less, but only in that case.
Is there a system that, if there are enough resources, runs requestAnimationFrame at something other than 60fps?
What are some techniques or methods that could potentially reduce jank and/or improve paint times on browsers?
There isn't an exact answer for this but here are some high level techniques that may work for most situations
Reduce paint layers - Use the browser's dev tools to see how many layers your css or markup may produce. Changing or simplifying your css could potentially reduce better outcomes
Frame Budget - If the JavaScript inside your requestAnimationFrame callback takes longer than 16ms to run, you don't have any hope of producing a frame in time for v-sync
Utlize a virtual dom, or Web Workers API - If possible offload processing away from the client and Utilize web workers api for processing
Sources:
Jank Busting
Gone in 60 Frames Per Second
I am currently developing a online networking game using Box2D JS and Vert.x as the server->client framework.
I have searched for pros and cons of each and I really believe that a dynamic time step is much better since it does not assume that each client has the same processing power, however, there are some (many) people that think fixed time step is much better.
Please enlighten me.
You can basically throw determinism out the window if your timesteps are not synchronized. Even when they are, determinism is difficult.
Spending less computation on simulation will have real costs that may not initially be apparent. For each different setting (and in the case of dynamic timesteps/iterations, for each different individual execution) the resulting behavior on the same input can be different. You can have a user run on really slow hardware that can potentially completely cheat through your levels.
Determinism is perhaps marginally less important outside of a multiplayer engine context, however simply not having a deterministic system will make it significantly more difficult to reason about pretty much anything (gameplay mechanics, game difficulty, exploits) which can impact nearly every kind of game I can think of. Imagine a puzzle game that wasn't deterministic.
I really believe fixing the timestep is the best way to go. I can't remember clearly enough but in one of our games we were having troubles with dynamic timesteps during collisions. Ofcourse most people would say our collision detection code was either not well written or we could use some advanced techniques like ray casting, but we ended up landing on fixed timestep with a for loop that would do the physics update whenever the delay seemed longer due to slow processing power of device or some other reason (CPU busy?), etc. The process was simple enough and we were all happy with the results :)
I think the creator of Box2D himself is in favour of fixed timestep, I read it somewhere although can't find the resource atm.
Can we assume that you are trying to get the same results for the simulation on all clients? If so I think you need to explain your reasoning why having them all doing different calculations would be a good idea!
Or perhaps you meant that all clients will do the same calculations, but the timestep will vary during as the simulation progresses, but that is quite the headache to implement and debug. For each client to come up with the same (or at least similar) result, they will need to be using the same length timestep for each step, so you will need to send this across the network too, eg. physics step 32241 is 16ms, step 32242 is 18ms. Apart from requiring extra network traffic, each client does not know what length timestep to use until it receives this information. And where does it receive it from? Presumably the slowest client will dictate how fast everybody should be going? I can't see it working any other way. So client also have to continuously let the server know how much processing they can handle, and the faster clients will be dragged down to that level of performance.
But as Steven says, there will also be other problems even after these technical difficulties have been taken care of. Most notably the effect of gravity changes with different timestep lengths, so for example in a platformer, the height your players can jump would be continuously changing. If there are platforms that are normally just reachable, they might suddenly become unreachable when a slower client joins.
If you really did mean that each client will use just whatever timestep length it feels like, that would work but the server would need to send out an official snapshot of the world state at very very frequent intervals to get all clients snyced. Technically this would be much easier to implement, and each client would run as smooth as it could, but with more jerkiness as the world state is corrected to the official one, for clients that run either faster or slower than the server does. Hm... maybe this is the best way after all. You might be interested in this article explaining how Quake3 does something like this: http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking