slowdown when drawing lines for >100objects in canvas

Get help using Construct 2

Post » Sun Jan 17, 2016 12:17 am

I made a directed graph conversation editor, it's working flawlessly, apart from one thing:

after I create more than 100 9-patch objects (dialogue nodes), that is about 824 objects, along with their contained objects (buttons, text), everything becomes sluggish. I get: 416 collisions per tick and 130 poly checks per tick, which doesn't sound huge. FPS drops to 9, CPU usage becomes 86% whenever I create a new one and goes back to 60 and 2% if I leave it alone.

The project is using @R0j0hound 's Canvas plugin, to render the directional arrows every time the user clicks, which is super fast up to a point. But maybe calculating arrows for more than 100 pairs of coordinates is too much. Is there a smart way to just calculate changed nodes, instead of all 100 at once? Perhaps a 2-step process of clearing the canvas?

Thanks in advance!

Here's the CAPX: https://dl.dropboxusercontent.com/u/28087823/LD34%20LandsOfLore/ConversationEditor/conv%20editor6.capx

Here it is in action: Image
B
28
S
12
G
4
Posts: 192
Reputation: 4,579

Post » Sun Jan 17, 2016 1:27 am

Using the draw line feature of the Canvas plugin is definitely what's killing performance here, especially since you have to redraw every line whenever something updates. There may be ways around erasing the whole canvas, but no matter what you'll have to redraw everything when you zoom in and out.

My suggestion would be to use Paster instead of canvas, which properly supports WebGL. It doesn't have line drawing support, but you should be able to get around this by pasting a rotated and stretched sprite.

EDIT: Upon further investigation, I take back everything -- will investigate more.
Moderator
B
113
S
41
G
20
Posts: 1,586
Reputation: 19,096

Post » Sun Jan 17, 2016 4:23 am

I'll have to look at your capx later when I'm home but here's a few thoughts:

If webgl is enabled I'd still recommend using the paster object because the canvas has to be copied to a webgl texture every tick that it changes. And actually the text object does the same thing so maybe you could use Spritefonts instead.
Actually if that is the bottleneck you can quickly check by setting webgl to off in the project settings. If the performance increases and the cpu usage goes down then I'd just leave webgl off, as it eliminates the need to copy the texture of the canvas and text instances.

Another thought is unless you're clicking or constantly checking what the mouse is over shouldn't the collision checks per second be 0? I guess I'll see when I open the capx.
B
89
S
30
G
95
Posts: 5,160
Reputation: 63,456

Post » Sun Jan 17, 2016 5:16 am

9 patch is like 9 objects in one.
Image ImageImage
B
166
S
49
G
155
Posts: 8,111
Reputation: 100,743

Post » Sun Jan 17, 2016 5:32 am

@newt
Not really. I mean you can think of it as a combination of sprites and tiled backgrounds when it's drawn, so as far as draw calls, maybe. In reality it's probably less, but that's not what's happening here IMO.
B
89
S
30
G
95
Posts: 5,160
Reputation: 63,456

Post » Sun Jan 17, 2016 7:39 am

@R0J0hound
Thats spot on. Just tested, spawning eats up fps, but it goes right back up to 60 even with hundreds of objects.
Guess there were some improvements I missed.
Image ImageImage
B
166
S
49
G
155
Posts: 8,111
Reputation: 100,743

Post » Sun Jan 17, 2016 11:00 am

Thanks everyone for taking the time <3

Performance is the same with or withoug WebGL.
I am making a few collision calls, mainly "cursor is over" and "cursor is not over". I don't know how to eliminate those while keeping the system intact. I now suspect spawning each node (1 container and 6 other objects) is too much for C2 after 100 have been already spawned.

I'm replacing canvas with Paster , and will report back
B
28
S
12
G
4
Posts: 192
Reputation: 4,579

Post » Sun Jan 17, 2016 12:22 pm

Hm other things that are unoptimized, working on them now:

1. every time I call for a canvas redraw, I ask for every node to be iterated. I should only request that children nodes that are on the screen be iterated. This doesn't help if there's 100 nodes on-screen, but does help when the editor is properly used, i.e. there's about 20 nodes on-screen.
2. each time I make a change, I make canvas reposition itself at the topLeft viewport. Maybe that takes a lot of processing power?
I also resize the canvas to WindowWidth/ layoutScale and windowHeight/layout scale, so that it's always as large as the window, regardless of zoom level. Maybe that's very calculations-intensive as well?


EDIT: The exact same thing happens with Paster, no improvement. Canvas isn't to blame.
When I remove all Text objects, also no improvement.

I think I may be making some rookie mistake with loops, or referencing objects that are off screen? :S

I don't get where all the collisions are coming from either, since collision checks are very strictly defined, and I've disabled most objects' collisions. Made all the optimization I knew how to make, updated the above CAPX file. Still, nothing.
B
28
S
12
G
4
Posts: 192
Reputation: 4,579

Post » Sun Jan 17, 2016 8:39 pm

Paster would only make a difference if webgl is used, and even then with one instance of the canvas it's not going to effect a whole lot.

Had a look at the capx. Nothing stands out as a problem. For me the debugger eats up the most of the cpu so maybe you could just add a fps counter to your game/app to get a better idea of the perfomance.

You're not running into an issue of drawing too much, at least not with 100 of your dialogs. Even the line drawing isn't causing much of a slowdown. I disabled drawing them and didn't notice much of a difference.

The collision checks are caused by the "overlapping", "on object clicked" and drag n drop behavior. I don't really see any place you can reduce those in your capx. You could reduce the amount of checks if you did something like the following so the top dialog and it's container are checked for hover and click events. If the click is elsewhere then the rest of the dialogs are checked. This should reduce the normal cpu usage. One caveat is hover effects only apply to the top dialog, and you may want it to work with everything.
Code: Select all
pick top dialog
mouse over dialog?
--- do stuff

on click
   local number case=0

   pick top dialog
   mouse over dialog?
   --- set case to 1
      mouse over button1
      --- do stuff
      mouse over button2
      --- do stuff
   case = 0
   mouse over dialog?
   pick top dialog
   --- set case to 1
   --- move to top
 
   case = 0
   --- //clicked on empty space



What the most likely cause for the slowdown is the high object count and the picking of events. If you can reduce the number of times you have to filter the SOL for an object. Not always possible but utilizing sub-events instead of picking from "all" can help.

The first culprits of events that slow things down are nested loops. In your "update canvas" function, it loops over each dialog and then each of it's children. One thing you could do to speed things up is to store the children's uids in the list so you can then use "pick by uid". Picking by uid basically picks the object directly, whereas using a comparison casuses all the objects to be checked.
A second idea would be to not store a list of the children but instead only store the uid of the parent. This would require reworking your event sheet but the result is much simpler. As a note if the dialog doesn't have a parent set the variable to -1.
Code: Select all
local number endx=0
local number endy=0
local number parent=-1

for each dialog
--- set endx to dialog.x
--- set endy to dialog.y
--- set parent to dialog.parent
   pick all dialog
   pick dialog by uid parent
   --- drawline from (dialog.x,dialog.y) to (endx,endy)


That way each dialog is looped over once and it's connected parent is picked directly. should be much faster.
B
89
S
30
G
95
Posts: 5,160
Reputation: 63,456

Post » Mon Jan 18, 2016 3:41 am

@r0j0hound so I'm not making super stupid mistakes? That's a huge relief. But your suggestions are still genius, thank you for going into the trouble to check all that undecipherable code! I'll implement right away and report back <3

Such an amazing performance boost, just from changing the picking system. @r0j0 you're the best. I've got 300 nodes and going! One tiny more thing now: zooming in and out still has a huge performance hit. Resizing and re-positioning the canvas seems to be very intensive. I made zooming less smooth (only three levels of zoom, you go to each one by rolling the mouse wheel, and that's it). But even then, I don't like the FPS drop spike, seems unstable

Here's the CAPX with my changes, for future reference of anyone who's interested:

https://dl.dropboxusercontent.com/u/28087823/LD34%20LandsOfLore/ConversationEditor/conv%20editor7.capx
B
28
S
12
G
4
Posts: 192
Reputation: 4,579

Next

Return to How do I....?

Who is online

Users browsing this forum: Ajbael and 6 guests