Ways to monitor image/transformation performance?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
octacon100
Regular
Posts: 163
Joined: Thu Sep 12, 2013 11:23 pm
Projects: Regeria Hope
Organization: Golden Game Barn
IRC Nick: Octacon100
Location: Boston, MA
Contact:

Ways to monitor image/transformation performance?

#1 Post by octacon100 »

Hi All,

I've been noticing that a lot of the animations in my game are kinda jittery, or sometimes just not happening, due to the number of frames being skipped. Initially I thought that this might be because images are being loaded into the cache, but even after giving the game a frankly ridiculous config.image_cache_size (around 500 MB) and a config.predict_statements of 50 I'm still seeing frames being skipped and images taking a while to appear. I'm wondering if I've got too many screens showing at once, or trying to do to many animations at once, maybe.

Are there ways to monitor which screens are currently being shown or how many images are currently stored? I've tried using the image load log with the developer menu, but not config.debug_image_cache. Is there something similar that shows screens currently shown or how much space is being used by Renpy?

Any info on performance tuning Renpy would be a very big help.

Looking at the image load log, I'm seeing that sometimes inventory images are loaded when the inventory is opened. Would it be worthwhile pre-caching images or transforms that I can tell will come up (like objections or interruptions) but it looks like Renpy doesn't pre-load? Looking around the forums, it seems like pre-caching is frowned upon, but could it help in this case?

I've tried using "subpixel True" on the transforms as well, but I'm not sure if that's helping or not.

Thanks in advance!
Image
Current Digital Projects -
Image
Regiera Hope Completed Game Forum Post

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Ways to monitor image/transformation performance?

#2 Post by xela »

octacon100 wrote:I've been noticing that a lot of the animations in my game are kinda jittery, or sometimes just not happening, due to the number of frames being skipped. Initially I thought that this might be because images are being loaded into the cache, but even after giving the game a frankly ridiculous config.image_cache_size (around 500 MB) and a config.predict_statements of 50 I'm still seeing frames being skipped and images taking a while to appear. I'm wondering if I've got too many screens showing at once, or trying to do to many animations at once, maybe.
500 MB is not much... I have 8GB RAM/2GB VRAM in my new Laptop (1 GB in the old one) and even that is not considered a lot these days. If you're releasing for handheld devices, you may want t look into using smaller images for them. Ren'Py is a 32 bit application so amount of RAM it can use is limited by that but calling 500 Mb for an advanced GUI/Graphics for modern machines is... "unusual".
octacon100 wrote:Are there ways to monitor which screens are currently being shown or how many images are currently stored? I've tried using the image load log with the developer menu, but not config.debug_image_cache. Is there something similar that shows screens currently shown or how much space is being used by Renpy?
None that I am aware of... You can always write a script looking for screen names in your .rpy files ("walking" through sub-folders is very easy in Python) and check for renpy.get_screen. Also you may get an idea about shown screen in Dev menu, styles often show that.
octacon100 wrote:Any info on performance tuning Renpy would be a very big help.
Predict all images, especially when using Python to show images and screens (normal prediction you get when using Ren'Py script doesn't work then).

When having to use "show" a lot (like in Battle engine or some for/while loop), try combining images instead using ATL or UDDs instead, renpy.show()/show have huge overheads, if you want to show 100 images really fast and iterate over something using show for each one, Ren'Py will skip animation and may even hang. UDD should handle the same thing without a hiccup.

One of the best advice came from Nyaatrap, use 2x smaller image and Transform(image, zoom=2) them. You'll find really decent performance boost and very little quality loss.

If you use buttons with focus_mask a lot, consider using a boundaries function instead of having Ren'Py figuring out where the transparent space is instead, that sometimes gives a decent boost.

If you keep using the same image a lot (like a frame behind items or a tile on a map for example), make sure it's the same one so you don't cache the same thing 20 - 30 times.

Use transitions well, they can sometimes behave oddly, especially when you're "showing" a lot of stuff in quick succession, switching from Dissolve to ATLing alpha channel did wonders in my BE designs just a few weeks back. Also if you have something that shows/hides images in quick sucession with Python, make sure that you add renpy.with_statement(None) before showing/hiding something with a transition because otherwise the transition will extend to previous show/hide funcs and mess you up.

Prolly more, but it's the usual stuff that is not unique to Ren'Py, you need good image prediction and handling even in "stronger" engines like Unity, so you can usually google this stuff for general rules/tricks.
octacon100 wrote:Looking at the image load log, I'm seeing that sometimes inventory images are loaded when the inventory is opened. Would it be worthwhile pre-caching images or transforms that I can tell will come up (like objections or interruptions) but it looks like Renpy doesn't pre-load? Looking around the forums, it seems like pre-caching is frowned upon, but could it help in this case?
No, it is worth (manually) predicting them. Don't do anything else unless/before manual prediction fails you (somehow).
octacon100 wrote:I've tried using "subpixel True" on the transforms as well, but I'm not sure if that's helping or not.
This is for smooth movement when precise movement is required, it will not do much for performance either way, logically I'd expect it to require more calculations but I have no proof of that, I often use it when smooth movement is required.
Like what we're doing? Support us at:
Image

User avatar
octacon100
Regular
Posts: 163
Joined: Thu Sep 12, 2013 11:23 pm
Projects: Regeria Hope
Organization: Golden Game Barn
IRC Nick: Octacon100
Location: Boston, MA
Contact:

Re: Ways to monitor image/transformation performance?

#3 Post by octacon100 »

Thanks xela! That's a bunch of great information. Looks like I need to read up on udds. Seems like this is it: http://www.renpy.org/doc/html/udd.html

Yeah, 500MB isn't much for graphics these days, I guess I was just thinking I was doing something wrong when I was going from the basic image cache size of 8 to 50. When it comes to performance tweaking this stuff, I know pretty much zero.

Good idea on the sprite size, I'm going to have to try that out I think.

I'll try some stuff out and let people know what helps here. I figure it might help someone else.
Image
Current Digital Projects -
Image
Regiera Hope Completed Game Forum Post

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Ways to monitor image/transformation performance?

#4 Post by xela »

octacon100 wrote:Thanks xela! That's a bunch of great information. Looks like I need to read up on udds. Seems like this is it: http://www.renpy.org/doc/html/udd.html
Yeah this is it, just keep in mind that this is only valid for complex minigames or a chain of dozens of shows. In my practice, there were two examples when switching to ATL or UDDs had a magical performance increase:

First was trying to show create a "vortex" that "sucks" a bunch of displayable in. I wrote a simple ATL that took properties and a function that provided well balanced data for that effect, created a list and iterated over it using renpy.show for each of the transform funcs. It did work but the effect was unacceptable (it showed 10 - 20 displayable, hang, showed some more and hang uttil there was nothing to show). The very same with rendered through UDD worked perfectly, I think it is because renpy.show has a huge overhead due to all the magic it needs to make happen internally.

Second was in my BE when I created an OrderedDict of time stamps and curried methods to show and hide chains of effects and attacks, same thing basically... it is a MUCH less then in vortex but still, every renpy.show call that I can get rid of in favor of tranform func, atl image or UDD gets rid of a small hiccup (I wish I could do the whole thing as a UDD but that's too much code).

==>
So this is only worth if you're showing many things in a quick succession, it'll pay off to bind as much as you can to one "tag" or screen whenever possible. For any other case it'll prolly be a lot of work for nothing.
Like what we're doing? Support us at:
Image

User avatar
octacon100
Regular
Posts: 163
Joined: Thu Sep 12, 2013 11:23 pm
Projects: Regeria Hope
Organization: Golden Game Barn
IRC Nick: Octacon100
Location: Boston, MA
Contact:

Re: Ways to monitor image/transformation performance?

#5 Post by octacon100 »

Ok, not sure if anyone is interested, but here's the results of my tweaking so far:

First up, easily the biggest performance booster was changing my timer from a screen language timer that ran python code to a UDD. That wins hands down. It looks like it also reduced the amount of re-caching of images the auto predictive image manager was doing. I was seeing examples of the same image being reloaded over and over again in the image log. Thanks to trooper6 for their UDD clock code I was able to tweak: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

The second biggest performance gain was from changing all the testimony animations from a series of shows like this:

Code: Select all

--snip--
            renpy.show(name=bg, at_list=[roomTransform])
            renpy.show(name=charImage, at_list=[charTransform])
            renpy.show(name=linesImage, at_list=[linesTransform], behind=[spriteName])
            renpy.with_statement(dissolve, always=False)
--snip--
to screen language like this:

Code: Select all

screen ScrZoomInLeftToMid(charSprite, bgSprite, charPos):
        tag rebuttalTransform
        
        on "show" action SetVariable("rebuttalTransformShown", True)
        on "hide" action SetVariable("rebuttalTransformShown", False)
        
        if persistent.animationsOn == True:
            add bgSprite at zoomInLeftToMidRoom(charPos)
            add "SprSpeedLinesLeftToRight"
            add charSprite at zoomInLeftToMid(charPos) 
After the screen show, these are very smooth. They are actually running on the phone version of the game now, instead of jumping all over the place, so I'm very happy about that.

I've tried predicting images, but I think I'm doing it wrong. Not quite sure where to go to figure out how to do it right. Haven't really seen any performance change there.

I've created screens for the shouts in the game as well, which are working great on the PC version, but not very well on the phone. Not entirely sure what is causing that. I'm hoping I can predict the screens before the shout and the loading of the screen will be better.

Here's an example shout screen, and the call that shows the screen. I must be doing something wrong with this for it to wig out and skip frames on the phone. All images are just images without their own transform code.

Code: Select all


-- The shout screen

screen regeriaHaltShout():
    zorder 200
    add "regeriaZoomImage" at bringInFaceFromRight
    add "interruptRightImage" at interruptRightTearTransformFast
    add "interruptRightSpeedLines" at interruptRightTransformFast
    add "haltNew" at interruptRightWordsTransformFast

-- Code to show the shout screen

label haltShout(override=False):
    
    call hideGUI from _call_hideGUI_9    
    play sound RegeriaHalt
    show screen regeriaHaltShout
    $ renpy.pause(1.0, hard=True)
    if (rebuttalTransformShown == False or (rebuttalTransformShown == True and persistent.animationsOn == False) or override==True ):
        if (rebuttalTransformShown == True):
            show screen ScrRebuttalTransform
            hide screen ScrRebuttalTransform
            with None
        show defence_side 
        show regeria Point at right
        with moveToDefence
    hide screen regeriaHaltShout
    with None
    call showGUI from _call_showGUI_8
    return

Image
Current Digital Projects -
Image
Regiera Hope Completed Game Forum Post

User avatar
octacon100
Regular
Posts: 163
Joined: Thu Sep 12, 2013 11:23 pm
Projects: Regeria Hope
Organization: Golden Game Barn
IRC Nick: Octacon100
Location: Boston, MA
Contact:

Re: Ways to monitor image/transformation performance?

#6 Post by octacon100 »

Another thing I'm thinking will help is changing my transitions to use ATL code instead, I get the feeling it will speed things up a lot:

So

Code: Select all

define moveToDefence = ComposeTransition(dissolve, before=moveoutleft, after=moveinright)
becomes something like:

Code: Select all

transform moveToDefence(new_widget, old_widget):
    
    contains:
        new_widget
        xpos 1366
        alpha 0.2
        ease 1.0 alpha 1.0 xpos 0
        
    contains:
        old_widget
        xpos 0
        alpha 1.0
        ease 1.0 alpha 0.0 xpos -1366

Thanks to Donmai for putting this post up, it really helps.:
http://lemmasoft.renai.us/forums/viewto ... 64#p345408
Image
Current Digital Projects -
Image
Regiera Hope Completed Game Forum Post

User avatar
octacon100
Regular
Posts: 163
Joined: Thu Sep 12, 2013 11:23 pm
Projects: Regeria Hope
Organization: Golden Game Barn
IRC Nick: Octacon100
Location: Boston, MA
Contact:

Re: Ways to monitor image/transformation performance?

#7 Post by octacon100 »

Ok, so here's an update.

- Making your own ATL to do transitions seemed to really, really speed up my transitions. I'd recommend that if you have a lot of transitions.

- Halving the size of images and using zoom 2.0 will really increase the number of images you can store in your cache.

- I'm having difficulty trying to figure out exactly how image prediction and image caching works. You can see how the image cache is working by using "config.debug_image_cache = True". Look in the "image_cache.txt" that will be created in the folder your log.txt is created in. You'll see a bunch of text.
--- Things to look for (This might be wrong, but it seems to be how it works.)
--Total Miss - This means that Renpy didn't predict this, and needed to load it into the cache as it was shown, so you might see some jittering and missed frames. You are likely to see something like this if you have an inventory screen.
-- Overfull - Means the image cache is totally full, and the image on this line couldn't be loaded.
-- Added - Means an image was added to the image cache.
-- Kept - Means an image has been kept in the image cache. Usually this will be images that you predicted.

-- Here's an example of how I do image prediction. It doesn't seem to work very well right now. It seems like you need predict an image then have a say transaction (Character says a word) before the image is actually shown?

Here's the code:

Code: Select all


label defenceToProsc(show_item="artemis Normal", show_background="pros_side", override=False):
    $ renpy.start_predict(show_item)
    $ renpy.start_predict(show_background)
    if (rebuttalTransformShown == False or (rebuttalTransformShown == True and persistent.animationsOn == False) or override==True ):
        window hide
        call hideGUI
        if (persistent.animationsOn == True):
            show screen ScrRebuttalTransform
            hide screen ScrRebuttalTransform
        $ renpy.scene()
        $ renpy.show(show_background)
        $ showImageLeft = False
        $ renpy.show (show_item, at_list=[left])
        with moveToProsc
        call showGUI
        window show
    else:
        $ renpy.scene()
        $ renpy.show(show_background)
        $ showImageLeft = False
        $ renpy.show (show_item, at_list=[left])
        with None
    $ renpy.stop_predict(show_item)
    $ renpy.stop_predict(show_background)
    return

Image
Current Digital Projects -
Image
Regiera Hope Completed Game Forum Post

User avatar
octacon100
Regular
Posts: 163
Joined: Thu Sep 12, 2013 11:23 pm
Projects: Regeria Hope
Organization: Golden Game Barn
IRC Nick: Octacon100
Location: Boston, MA
Contact:

Re: Ways to monitor image/transformation performance?

#8 Post by octacon100 »

Another update, the phone version is now looking much better.

-A couple of points I hope will help other people:

- You need to predict your images a renpy statement (Like when a character says something) or two before you actually use the image. My previous prediction code tried to do a prediction and show an image immediately after it and that didn't work, I got a bunch of total misses.

- As RenpyTom mentioned in another post, if you need to have text buttons that cover an entire screen to stop users from clicking to advance, use "None" as your background instead of something like "#0000" as that will create a big transparent image.

-If you are creating frames you want to cover the entire screen, make sure that padding and margins are set to 0 and your xfill and yfill are true. Don't make a huge 4000 x 4000 frame like I did with a transparent background and wonder why your RAM is filled up. (Doh!)

-If you are showing a bunch of screens (like one for every button you have) consider making a screen that "uses" those screens, and uses variables to determine weather they are being used or not. That seems to have sped things up. It has at least reduced the number of "shows", so I think it's a good thing?

-When you predict screens with variables, only the last copy of the prediction and variable call will be predicted. So renpy.start_predict_screen("blah", "blah") followed by renpy.start_predict_screen("blah", "blah2") will only keep renpy.start_predict_screen("blah", "blah2") in memory.

-When you are using renpy.start_predict() and want to free up some memory, use renpy.stop_predict() and then renpy.free_memory(). Keep an eye on your processes in task manager and your image cache file and you'll be able to see changes.

Hopefully this helps some people. I'm not an expert on this, so I there's any other tips that people have or anything I could have done better, please let me know.
Image
Current Digital Projects -
Image
Regiera Hope Completed Game Forum Post

Post Reply

Who is online

Users browsing this forum: No registered users