Laggy City Interface

Things I would try for experimentation:

Prove it's not your graphics

1. Pull out a single button for a known vanilla building outside the loop into a variable and use that inside the loop instead of accessing your building.

Code:
[B]szButton = gc.getBuildingInfo(0).getButton()[/B]
for ...
    screen.appendMultiListButton( "BottomButtonContainer", [B]szButton[/B], ...)

1a. If that goes much quicker, check getButton() vs. using the button. With the same code, insert one line:

Code:
[B]gc.getBuildingInfo(eLoopBuilding).getButton()[/B]
screen.appendMultiListButton(...)

1b. If that is slow again, check getButton() vs. getBuildingInfo(). Again, modifying the same code:

Code:
[B]gc.getBuildingInfo(eLoopBuilding)[/B]
screen.appendMultiListButton(...)

1c. If that is slow, something is amiss with accessing the building. If it's fast again, getButton() is slow.

Hide control, add buttons, show

If 1a doesn't speed it up, the buttons aren't the problem. Perhaps adding each button causes the screen to call update()? This could be slow if RevDCM adds slow code to CvMainInterface.update() (or updateScreen() or whatever it's called).

Try hiding the control before adding all the buttons and showing it at the end.

Code:
screen.hide("BottomButtonContainer")
for ...
    ...
screen.show("BottomButtonContainer")

I think there's a call to show() inside the loop. Remove it.

Report back everything you find for each step, and hopefully we can figure out what's happening.
 
Things I would try for experimentation:

Prove it's not your graphics

1. Pull out a single button for a known vanilla building outside the loop into a variable and use that inside the loop instead of accessing your building.

Code:
[B]szButton = gc.getBuildingInfo(0).getButton()[/B]
for ...
    screen.appendMultiListButton( "BottomButtonContainer", [B]szButton[/B], ...)

1a. If that goes much quicker, check getButton() vs. using the button. With the same code, insert one line:

Code:
[B]gc.getBuildingInfo(eLoopBuilding).getButton()[/B]
screen.appendMultiListButton(...)

1b. If that is slow again, check getButton() vs. getBuildingInfo(). Again, modifying the same code:

Code:
[B]gc.getBuildingInfo(eLoopBuilding)[/B]
screen.appendMultiListButton(...)

1c. If that is slow, something is amiss with accessing the building. If it's fast again, getButton() is slow.

Creating a button variable outside the loop and referencing it every time inside the loop instead of looking up the button had no effect on the call length. Most buildings still took between 15-50 ms.

Hide control, add buttons, show

If 1a doesn't speed it up, the buttons aren't the problem. Perhaps adding each button causes the screen to call update()? This could be slow if RevDCM adds slow code to CvMainInterface.update() (or updateScreen() or whatever it's called).

Try hiding the control before adding all the buttons and showing it at the end.

Code:
screen.hide("BottomButtonContainer")
for ...
    ...
screen.show("BottomButtonContainer")

I think there's a call to show() inside the loop. Remove it.

Report back everything you find for each step, and hopefully we can figure out what's happening.


This had no effect on the length of time as well.
 
Okay, one more. Revert to the original code and comment out the call to appendMultiListButton(). If that's not faster, also comment out the call to show() inside the loop.
 
Commenting out the appendMultiListButton() calls made the entire loop take 6ms.
 
Okay, here's the fun part. For every function in CvMainInterface insert a line at the top that logs the function name using BugUtil.debug(). For example:

Code:
def update(self, ...):
    [B]BugUtil.debug("update")[/B]
    ...

That part will suck to do, but the "quicker" solution would take much longer to build.

Then place a similar message inside the loop that is adding icons to that panel:

Code:
for ...
    [B]BugUtil.debug("can build building #%d", i)[/B]
    ...

In that new line, the "i" must be whatever the loop variable is in that loop, i or eBuilding or iLoopBuilding; whatever. Just make it match.

Run again and see if you see any of those extra debug messages appearing between the "can build building #X" messages.

Weeee fun!
 
Your idea of fun is sick and twisted, you know that?

Okay, I'll do it, and report back.
 
Okay I see a TON of debugging info, what am I looking for here?
 
You should see a list of building #s:

Code:
can build building #1
can build building #5
can build building #8
can build building #9
can build building #10
can build building #12
...

If you see any of those other debug messages sprinkled in among them, that is the problem. Post PythonDbg.log as I'm curious to see what it says.
 
You should see a list of building #s:

Code:
can build building #1
can build building #5
can build building #8
can build building #9
can build building #10
can build building #12
...

If you see any of those other debug messages sprinkled in among them, that is the problem. Post PythonDbg.log as I'm curious to see what it says.

The buildings are in perfect sequence, in relation to the loop, no interrupting refreshes.

View attachment PythonDbg.rar
 
At this point, it looks like the problem really is adding the buttons to that control. You said that swapping in a single static button (one from a vanilla building, right?) had no effect on the overall time?
\
That means it's not your new button art that is the problem--it's that you simply have too many buildings. And you're sure that hide()ing first and show()ing at the end didn't speed it up? And there's no appendMultiListButtonNoUpdate() version of the function. :(

One option, though it sucks from a UI perspective, would be to split the list into three tabs where you draw only the units, or only the buildings, or only the wonders/projects/processes. Those little buttons on the right would no longer "jump" to that point in the list but redraw the list for that section.

This would only be worthwhile if drawing the units was a significant portion of the draw time. If the units only add 100ms, it's not worth it. Heck, even 300 probably isn't worth it really. It would have to be at least 500ms for the units to offset the extra effort of clicking buttons.
 
Hmm.

Okay, while what I don't get is why looping through 270 units in RoM consumes approx 30 ms of time, to add the unit icons and everything, but looping through 440 buildings consumes 800 ms of time to add a similar amount of icons. They call the same exact function, but the unit calls take no time at all.

Is there a difference we are seeing vs Atlas'ed and individualized buttons? I know the units all use a big atlas for their buttons, but about 200 of the buildings have their own separate button, w/o an atlas. I wonder if there is a correlation here.
 
What happens if you comment out the entire unit loop so that the building icons are the first buttons added to the list? Do they still take the same amount of time? What I'm thinking is that each time you add a button it has to redraw all the buttons. Thus the first button takes 1x; the second 2x; the third 3x; etc.

How many buttons total--of each type--get added to the list in your testing?
 
It added 21 unit buttons in ~15 ms. Then it added 37 building buttons for a total of 753 ms.

That is why I still believe we are missing something. Aren't those running identical loops?
 
Yes, the only difference being the button art added and that the buildings come after the units. Did commenting out the unit loop change the building loop time?
 
No, removing the unit loop had no effect on the time for the building loop.
 
Perhaps adding each button causes the screen to call update()? This could be slow if RevDCM adds slow code to CvMainInterface.update() (or updateScreen() or whatever it's called).

We are all throwing ideas, but here is one. We know that vanilla can draw both unit and building buttons fast, and we now see your mod can draw unit buttons fast but building buttons are slow. Maybe something else on the screen is updated for each building button. BUG displays a lot more icons and graphics on the screen. A lot of these can be turned off by configuration options in the BUG control panel. Can you identify some icons and graphics added by BUG, and use the control panel to turn them off? Perhaps the redraw of these other elements is taking the time.
 
We are all throwing ideas, but here is one. We know that vanilla can draw both unit and building buttons fast, and we now see your mod can draw unit buttons fast but building buttons are slow. Maybe something else on the screen is updated for each building button. BUG displays a lot more icons and graphics on the screen. A lot of these can be turned off by configuration options in the BUG control panel. Can you identify some icons and graphics added by BUG, and use the control panel to turn them off? Perhaps the redraw of these other elements is taking the time.

Correct me if I am wrong, but I thought I ruled that out by adding all the BugUtil statements that showed when each function was run, and that nothing was interrupting or redrawn in the city queue.
 
I thought I ruled that out by adding all the BugUtil statements that showed when each function was run, and that nothing was interrupting or redrawn in the city queue.

Correct. All of the stuff BUG adds to the screen is drawn by the functions in CvMainInterface. Even if not, I would expect those functions to be called for the unit icons as well.

The only other difference between the unit and building loops I can think of is that each block of icons is added to a line. Units on 0 (or 1?), buildings on 1 (or 2?). With the unit code commented out, change the building appendMultiListButton() call to use the line the units code uses. I really doubt that is the problem.

How confident are you that you did all the trials I suggested exactly as I suggested? I was really hoping it would be a particular button that was tripping the graphics engine up and that using a single button from vanilla for all buildings would make it go fast. :(
 
How confident are you that you did all the trials I suggested exactly as I suggested? I was really hoping it would be a particular button that was tripping the graphics engine up and that using a single button from vanilla for all buildings would make it go fast. :(

I double checked this again, by using a unit button (the warrior button) for all the buildings instead of looking up the button. The time was the same.

However, I noticed some odd results when I changed the Widgettypes.WIDGET_CONSTRUCT to WIDGET_TRAIN. The loop went much much quicker. Is it possible than the Construct Widget has something in it that is making it take longer?
 
Good forensics work; I didn't think of that part. The WidgetType controls two things (in the SDK): hover and click. However, that doesn't stop it from affecting something in the EXE.

The question remains: what could it possibly affect? The only visual difference is controlled by CvCity::canConstruct() (two calls), but those are called from Python and commenting them out didn't affect the time. Thus if the EXE was also calling them they shouldn't be an issue here either.

I suggest scouring the SDK for all uses of WidgetTypes (Find all References in VS) and looking for something unexpected.
 
Back
Top Bottom