A couple ZScript performance questions

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
D2JK
Posts: 545
Joined: Sat Aug 30, 2014 8:21 am

A couple ZScript performance questions

Post by D2JK »

Since I couldn't find a generic performance questions topic or sticky (should we have one?), I'll just ask here. I don't mind if others want to post their questions in this thread, too.

1) About variable optimization... is it beneficial pay attention and optimize variable sizes, for example using int8 (1 byte) instead of int (4 bytes) when the former is sufficient? Now, before you think "use some common sense", the reason for me asking this is that on the net (and perhaps even on this board, can't remember for sure), I've heard something to the effect that for PC, the natural data type is 32 bits. So while it's not that I'm worried about running out of memory, I'd like to be sure that by 'optimizing' variables, I'm not making the performance any worse, at least.

2) It's been advised not to use "functions inside functions (that are inside functions, and so on)", because of degraded performance. But do anonymous functions, created within actor states, already count as one? And I'm guessing, function-like macro definitions do not count, is that correct?


In addition to minding these, I've learned that there might be some performance gains by converting 'actors' into 'thinkers', where applicable.
Last edited by Rachael on Fri Dec 21, 2018 1:29 pm, edited 1 time in total.
Reason: Topic title renamed, made the thread singular purpose rather than generic.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: Performance questions

Post by Apeirogon »

Gzdoom have console commands for performance check, profilethinkers and stats. First can show how much time and times some actor class on a map call its functions, second have several...debug I think commands which can show how much vram takes gzdoom, vm calls, etc.
So you can check optimizations of you code by yourself.
gramps
Posts: 300
Joined: Thu Oct 18, 2018 2:16 pm

Re: Performance questions

Post by gramps »

Not sure about the first question.

About the second thing, I guess those anonymous functions in Decorate were added pretty recently; I don't remember them being around when I used to mess with this stuff. But I don't think they'd suffer from the same problems you're thinking of. Really they look more like regular old blocks of code than functions. They don't take any arguments, or return anything, but more importantly they don't need any closed-over values from outer scopes.

Consider this (contrived) Lua code:

for i = 1, 10 do (function() print(i) end)() end

There's an anonymous function that prints *i*. But what is *i*? For the first invocation, it's 1, then it's 2, etc. One way to look at this, depending on what the interpreter actually does with this code, is as ten different functions, each bound to a different *i*. That *i* value is what I mean by a "closed-over value" (Lua calls these "upvalues"). Long story short, I don't think you need to worry about that kind of thing in Decorate.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49234
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Performance questions

Post by Graf Zahl »

Every function in DECORATE that takes some parameters generates an anonymous function, even something seemingly banal as "A_Explode(64)".
Unless you start to write really complex stuff in ZScript there is no need to worry. A function like A_Explode runs at least 3-4 times longer than the small anonymous VM function. In such cases the time spent in the VM can be measured in microseconds.
User avatar
Rachael
Posts: 13954
Joined: Tue Jan 13, 2004 1:31 pm
Preferred Pronouns: She/Her
Contact:

Re: Performance questions

Post by Rachael »

D2JK wrote:Since I couldn't find a generic performance questions topic or sticky (should we have one?)
No. We discourage "generic threads" because it encourages question dump and people pile on questions before any of them ever get answered. If you need to ask a question, please just make a thread! Even if it's minor! It's not going to hurt you.
D2JK
Posts: 545
Joined: Sat Aug 30, 2014 8:21 am

Re: A couple ZScript performance questions

Post by D2JK »

Thanks for the input, everyone.

The variable optimization question was left unanswered, but I'll look into the console commands mentioned by Apeirogon, and try to create some kind of an isolated test scenario. I'll report back if anything useful turns up.
User avatar
phantombeta
Posts: 2177
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: A couple ZScript performance questions

Post by phantombeta »

You shouldn't really try to optimize variable sizes - The non-32-bit ints tend to be buggy, and don't work too well, while the 32-bit floats barely work, and are silently replaced with doubles in functions.
Basically, the non-32-bit ints and non-double floats were added just so things could be exported to ZScript.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49234
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: A couple ZScript performance questions

Post by Graf Zahl »

Actually, they were just exported because when I considered removing them a few people who were VERY concerned about saving space were about to create a shitstorm over it. Changing the backing store for the native fields to 32 bit would have been a better solution, actually. Their actual value is close to zero, unless you define large arrays of range-restricted values.

For local variables they can't even be used because the VM registers are 32 bit for int and 64 bit for float, they cannot even hold those smaller types without extending them.

Just coincidentally, just a few days ago I had to fix another one of those space-saving disasters from many years back where using a 16 bit value was deemed enough at the time, effectively reducing the usability of the feature it was used for.
D2JK
Posts: 545
Joined: Sat Aug 30, 2014 8:21 am

Re: A couple ZScript performance questions

Post by D2JK »

I've been running some tests on an actor that attempts to detect nearby enemies.

Code: Select all

 A_LookEx(LOF_NOJUMP | LOF_NOSOUNDCHECK, 0, 10, 0, 360);

 if ( target  &&  Distance3D(target) < 40 )
 {
 }

Code: Select all

 actor M;
 ThinkerIterator Searcher = ThinkerIterator.Create("MyMonster", STAT_DEFAULT);

 while ( M = MyMonster(Searcher.Next()) )
   if ( M  &&  !M.bFriendly  &&  M.health > 0  &&  Distance3D(M) < 40 )
   {
   }
The iterator-based search is ~25% slower compared to the action function. I was wondering why is A_LookEx more efficient, even though I've tried to keep the iterator search as minimal as possible?
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: A couple ZScript performance questions

Post by Apeirogon »

A_lookex runs directly on cpu, while thinker iterator on virtual machine, in short.
D2JK
Posts: 545
Joined: Sat Aug 30, 2014 8:21 am

Re: A couple ZScript performance questions

Post by D2JK »

Ok. I take it there's no way for me to improve the iterator's performance any further.
User avatar
phantombeta
Posts: 2177
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: A couple ZScript performance questions

Post by phantombeta »

First of all, both run on the CPU on the latest devbuild (and in the next GZDoom release)
But this isn't the only reason for the perfomance difference. Friendly monsters find enemies to attack by doing a blockmap search with a very short range, not a ThinkerIterator, so that's also likely part of the performance difference.
D2JK
Posts: 545
Joined: Sat Aug 30, 2014 8:21 am

Re: A couple ZScript performance questions

Post by D2JK »

I measured the performance after updating to the latest build and re-reading the thread where Major Cooke and Graf Zahl discussed iterators and stat numbers. Here the STAT_MONSTERS - iterator is using a stat number I've applied to monster classes only, so the search becomes much more limited. The iterator type used is ThinkerIterator, and the think times in chart are ms.
Attachments
Iterator test.jpg
Iterator test.jpg (12.83 KiB) Viewed 736 times
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49234
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: A couple ZScript performance questions

Post by Graf Zahl »

How many monsters are you talking about? The default iterator won't indeed scale well with small numbers because it still needs to iterate over all 128 STAT slots, most of which are empty.
D2JK
Posts: 545
Joined: Sat Aug 30, 2014 8:21 am

Re: A couple ZScript performance questions

Post by D2JK »

In the above test, there were 100 monsters in the map.
Post Reply

Return to “Scripting”