I have started looking into the client side performance of my app using Chrome's Timeline tools. However, whilst I have found many articles on how to use them, information on how to interpret the results is more sparse and often vague.
Currently I am looking at scroll performance and attempting to hit 60FPS.
This screenshot show's the results of my most recent timeline recording.
As can be seen most frames are over 60 FPS and several are over 30 FPS.
If I zoom in on one particular frame - the one with duration 67.076ms I can see a few things:
the duration of the frame is 67ms, but aggregated time is 204ms
201ms of this time is spent painting BUT the two paint events in
this frame are of duration 1.327 ms and 0.106 ms
The total duration for the JS event, update layer tree and paint events is
only 2.4 ms
There is a long green hollow bar (rasterize Paint)
which lasts the duration of the frame and in fact starts before and
continues after it.
I have a few questions on this:
the aggregated time is far longer than the frame time - is it
correct to assume that these are parrallel processes?
the paint time for the frame (204ms) far exceeds the time for the two paint events (1.433ms) - is this because it includes the
rasterize paint events
why does the rasterize paint event span multiple frames?
where would one start optimizing this?
Finally can someone point me to some good resources on understanding this?
This is somewhat unfortunate result of the way the 'classic' waterfall Timeline view coalesces multiple events. If you expand that long "Rasterize Paint" event, you'll see a bunch of individual events, which are going to be somewhat shorter. You may really want to switch to Flame Chart mode for troubleshooting rendering performance, where the rasterize events are shown on appropriate threads.
Related
I want to be able to display and close an image within a few miliseonds.
I generally understand how to do this for a few seconds, but how can I achieve accurate milisecond rendering?
What is the approach to ensure that I can be certain an image has only been open for 10 miliseconds or even 5 milisecond and that my monitor has indeed displayed this image (assuming I have for example a 240hz monitor).
From my limited understanding of a monitors refresh rate, a 240hz monitor may refresh the display 240 times a second which is around every 4 miliseconds. If I want to display something for 5 miliseconds, it's possible that more than half that time my monitor hasn't really been refreshing (therefore not displaying). Under that logic is it correct that I would need to display the image for around 4 or 8 miliseconds? Is there a way to synchronize my displays refresh rate with the output of my program?
I'm planning to do this in c++ although the language isn't too critical provided the problem can be solved. I haven't managed to find any sources on how to approach this sort of problem. Is there any direction to a solution for this sort of problem?
This sync'ing is known as V-sync (Vertical Sync), since displays are typically oriented in horizontal lines. That means an entire screen is shown after the last line is drawn, just before the next line at the top of the screen will be drawn. I.e. the V-sync event is the vertical wrap-around.
You need a game-oriented API like DirectX or OpenGL
I've made a game on pixi.js where it is very simple and should run smoothly but doesn't. Since the game is big and has lots of elements I don't know where the bottleneck is. I believe some part/s of the is buggy resulting in lots of resource usage.
I want to learn the method on how to identify the functions I wrote that use up a lot of resources.
When I use default chrome tools they never show the part of the code that I wrote but always the library ticker: https://prnt.sc/qiplql.
This doesn't help me, I want to know which functions I wrote that is being called many times and uses up a lot of resources.
What is a way I can do this?
Here is our debugging server where the code isn't minimized.
Zoom in
To get the most out of the performance monitor you must zoom into the timeline and investigate small sections of code.
The image below shows the section of the timeline, and the Call tree's representation of that small section of time
Find a single frame
However this still is too much information. Zoom right in to find a single frame that is running long (over 16ms)
Use the graphical call tree (open fold main)
The next image shows a long frame (25ms) Opening the fold main (on left) will show a graphical representation of the call tree.
The frame is started with a long task triggered by a mouse up event. At the bottom of that stack the reason the event takes so long is the DOM recalculating the style.
The recalculation of the style meant that the next requestAnimationFrame callback had some extra baggage before (reflow) and after the script (DOM rendering and compositing) meaning the frame was late to present.
Zooming in on the requestAnimationFrame there are no problems. Just as an example I zoomed so you can see how the graphical representation relates to the Call tree. I have drawn some lines connecting graphical function calls with the same call in the call tree.
Many reasons
To find your bottle necks you will have to zoom right in on the slow frames. There may be many different reasons that frames are slow.
What does it mean, when you have slow frames (those ones indicated with red triangles) in Chrome Dev Tools' Timeline, but it doesn't show what causes that (script, render, composition, etc). It's like nothing really happens but you still have janks.
If you click on the time-span above the main thread, and then click on the Bottom-Up tab at the bottom, you can see all the individual activities going on that add up to that total time. I suspect there must be some other activities you can't currently see, but if you scroll vertically, you should see them - probably Rasterize Paint on another worker.
Update
I realised that the times in the Bottom-Up view do not add up to the total time shown for the frame. I did a little more playing and it looks as though the remaining time is 'Idle' time.
If you look at the screenshot below, I have adjusted the Timeline view to contain approximately one frame that has very minimal activity. It's a little bit more than one frame because you can see the dotted lines on either side are a little further in.
If you then look at the bottom Summary view, you can see the majority of time is listed as 'Idle'. If you pretend I more accurately filtered the Timeline view to be exactly one frame (by taking off a tiny bit of time from the summary values), you could probably fairly confidently come to the conclusion that the total frame time (shown just above the Main Thread bar) is the summation of the values shown in Summary, including the 'Idle' time.
I am drawing an animation using double-buffered GDI on a window, on a system where DWM composition is enabled, and seeing clearly visible tearing onscreen. Is there a way to prevent this?
Details
The animation takes the same image, and moves it right to left over the screen; the number of pixels across is determined by the difference between the current time and the time the animation started and the time to end, to get a fraction complete which is applied to the whole window width, using timeGetTime with a 1ms resolution. The animation draws in a loop without processing application messages; it calls the (VCL library) method Repaint which internally invalidates and then calls UpdateWindow for the window in question, directly calling into the message procedure with WM_PAINT. The VCL implementation of the paint handler uses BeginBufferedPaint. Painting is itself double-buffered.
The aim of this is to have as high a frame-rate as possible to get a smooth animation across the screen. (The drawing uses double-buffering to remove flickering and to ensure a whole image or frame is onscreen at any one time. It invalidates and updates directly by calling into the message procedure, without doing other message processing. Painting is implemented using modern techniques (eg BeginBufferedPaint) for Aero composition.) Within this, painting is done in a couple of BitBlt calls (one for the left side of the animation, ie what's moving offscreen, and one for the right side of the animation, ie what's moving onscreen.)
When watching the animation, there is clearly visible tearing. This occurs on Windows Vista, 7 and 8.1 on multiple systems with different graphics cards.
My approach to handle this has been to reduce the rate at which it is drawing, or to try to wait for VSync before painting again. This might be the wrong approach, so the answer to this question might be "Do something else completely: X". If so, great :)
(What I'd really like is a way to ask the DWM to compose / use only fully-painted frames for this specific window.)
I've tried the following approaches, none of which remove all visible tearing. Therefore the question is, Is it possible to avoid tearing when using DWM composition, and if so how?
Approaches tried:
Getting the monitor refresh rate via GetDeviceCaps(Application.MainForm.Handle, VREFRESH); sleeping for 1 / refresh rate milliseconds. Slightly improved over painting as fast as possible, but may be wishful thinking. Perceptually slightly less smooth animation rate. (Tweaks: normal Sleep and a high-resolution spin-wait using timeGetTime.)
Using DwmSetPresentParameters to try to limit updating to the same rate at which the code draws. (Variations: lots of buffers (cBuffer = 8) (no visible effect); specifying a source rate of monitor refresh rate / 1 and sleeping using the above code (the same as just trying the sleeping approach); specifying a refresh per frame of 1, 10, etc (no visible effect); changing the source frame coverage (no visible effect.)
Using DwmGetCompositionTimingInfo in a variety of ways:
While cFramesPending > 0, spin;
Get cFrame (frame composed) and spin while this number doesn't change;
Get cFrameDisplayed and spin while this doesn't change;
Calculating a time to sleep to by adding qpcVBlank + qpcRefreshPeriod, and then while QueryPerformanceCounter returns a time less than this, spin
All these approaches have also been varied by painting, then spinning/sleeping before painting again; or the reverse: sleeping and then painting.
Few seem to have any visible effect and what effect there is is hard to qualify and may just be a result of a lower frame rate. None prevent tearing, ie none make the DWM compose the window with a "whole" copy of the contents of the window's DC.
Advice appreciated :)
Since you're using BitBlt, make sure your DIBs are 4-bytes / pixel. With 3 bytes / pixel, GDI is horribly slow while DWM is running, that could be the source of your tearing. Another BitBlt issue I've run into, if your DIB is somewhat larger, than the BitBlt call make take an unexpectedly long time. If you split up one call into smaller calls than only draw a portion of the data, it might help. Both of these items helped me for my case, only because BitBlt itself was running too slow, thus leading to video artifacts.
I'm making a snake game and on every tick the snake moves. because the snake is moving a whole unit on each tick the animation is jumpy. The game is on an invisable grid so the snake can only change directions at specific points.
Would it be considered better practice to have a timer that will move the snake a pixels at a time counting it with a variable, and on every n tick run the code to change direction. Or is it better to have two separate timers; one for move the snake a pixel at a time and another for changing the snakes direction?
Essentially, you're creating a "game-loop" to update the displayList (in Actionscript) and re-draw your view. When the game gets complex, Timers and listening for ENTER_FRAME events will be constrained to the flashplayer settings for screen refresh (i.e. it's FPS) and the CPU's rendering based on what it is tasked to process.
For frame-rate independent animation, you should probably use a combination of ENTER_FRAME to track milliseconds and GetTimer() calls to more accurately (to the millisecond) call animations and normalize the experience across a variety of platforms.
Basically, listen for the ENTER_FRAME event, check the current milliseconds since the last update and if it exceeds your refresh-rate (in terms of milli's), fire off the animation/state update: check for snake collision detection with a "direction-block" - handle if true, then update the snake's movement / position / state.
Flash updates the Display List at whatever it's settings, and CPU / machine-dependent issues are. The key, I've found, is to make sure you're normalizing the speed of updates to make the experience consistent. Timer's have their usage, but can cause memory performance issues. ENTER_FRAME is synced to the main timeline / frame-rate settings.
For a dated, but interesting discussion 3 years ago, check out this post from actionscript.org.