Jump to content


Photo

Optimizing your game further


  • This topic is locked This topic is locked
18 replies to this topic

#1 kibblesbob

kibblesbob

    "Xarrot Studios"

  • GMC Member
  • 215 posts
  • Version:GM:Studio

Posted 08 March 2012 - 03:14 AM

Ok, so I was working with a giant loop, and I had many scripts running inside this loop at once, doing lots of calculations and drawing primitives and what not. I was trying to optimize it, shorten any code I could, and simplify every process that needed to be calculated. But I still wanted more. It didn't occur to me that I could actually be slowing my game down with using scripts, the length of the scripts name, and the content and format of the script itself, until I removed a script and replaced it with only GML. It increased my total FPS from 21-29, to around 24-36. I was amazed! The scripts being called, even though not much was going on in them, were slowing the game down!

Around this time, I decided to do a few tests, and I worked them out all under the same circumstances:
- No other programs running during all testing
- Kept the same room-size throughout each test ( 32x32 ), no drawing, black background
- Only made changes to the code in the create event of the one object I had in the room
- All tests were done seven times, consecutively
- Did not use the game_restart() function, just quit game and ran a new instance of the test
- Done in GM8 Registered

---Here are the tests ---


Test 1 : Executed the following piece of code WITHOUT the use of scripts

var t;
t = current_time;
repeat ( 25000 )
 { x = 0 ; y = 0 ; x = 0 ; y = 0 ; x = 0 ; y = 0 ; x = 0 ; y = 0; }
show_message((current_time-t));

Test 2 : Executed the following piece of code WITH a script called 'tst'

In this test, script 'tst' contained the following code:

repeat ( 4 )
 { x = 0 ; y = 0; }

The test was executed as follows:

var t;
t = current_time;
repeat ( 25000 )
 { tst(); }
show_message((current_time-t));


Test 3 : Executed the following piece of code WITH a script called 'tst'

In this test, script 'tst' contained the following code:

x = 0 ; y = 0;
x = 0 ; y = 0;
x = 0 ; y = 0;
x = 0 ; y = 0;

The test was executed exactly the same as Test 2


Test 4 : Executed the following piece of code WITH a script called 'tst'

In this test, script 'tst' contained the following code:

x = 0;
y = 0;
x = 0;
y = 0;
x = 0;
y = 0;
x = 0;
y = 0;

The test was executed exactly the same as Test 2 and Test 3


Test 5 : Executed the following piece of code WITH a script called 'tst'

In this test, script 'tst' contained the following code:

x = 0 ; y = 0 ; x = 0 ; y = 0 ; x = 0 ; y = 0 ; x = 0 ; y = 0;

The test was executed exactly the same as Test 2, Test 3, and Test 4


Test 6 : Executed the following piece of code WITH a script called 'one_big_gigantic_script_name_to_tst_this_scrpt_4real'

In this test, script 'one_big_gigantic_script_name_to_tst_this_scrpt_4real' contained the following code:

x = 0 ; y = 0 ; x = 0 ; y = 0 ; x = 0 ; y = 0 ; x = 0 ; y = 0;

The test was executed exactly the same as Test 2, Test 3, Test 4, and Test 5

---Here are the results ---


Test 1 : Average time to calculate: .11 seconds

Trial 1: .11s, Trial 2: .11s, Trial 3: .09s, Trial 4: .11s, Trial 5: .12s, Trial 6: .13s, Trial 7: .08s


Test 2 : Average time to calculate: 1.91 seconds

Trial 1: 1.89s, Trial 2: 1.93s, Trial 3: 1.90s, Trial 4: 1.92s, Trial 5: 1.90s, Trial 6: 1.86s, Trial 7: 1.97s


Test 3 : Average time to calculate: 1.84 seconds

Trial 1: 1.86s, Trial 2: 1.79s, Trial 3: 1.83s, Trial 4: 1.83s, Trial 5: 1.84s, Trial 6: 1.84s, Trial 7: 1.90s


Test 4 : Average time to calculate: 1.88 seconds

Trial 1: 1.98s, Trial 2: 1.83s, Trial 3: 1.93s, Trial 4: 1.79s, Trial 5: 1.84s, Trial 6: 1.92s, Trial 7: 1.86s


Test 5 : Average time to calculate: 1.82 seconds

Trial 1: 1.79s, Trial 2: 1.84s, Trial 3: 1.76s, Trial 4: 1.84s, Trial 5: 1.81s, Trial 6: 1.84s, Trial 7: 1.86s


Test 6 : Average time to calculate: 1.86 seconds

Trial 1: 1.87s, Trial 2: 1.86s, Trial 3: 1.92s, Trial 4: 1.78s, Trial 5: 1.86s, Trial 6: 1.83s, Trial 7: 1.89s


---Conclusions/What I learned ---


The most important thing I picked up from doing this test, is that scripts can slow down your game, albeit not by much. If you are using nested-loops and running scripts nested in scripts in those nested-loops, you may want to just bite the bullet and type it out into the code editor and ditch the scripts.

Secondly, make sure you condense your code as much as possible. That doesn't mean fit everything into one line, but make sure if you have extra lines at the end of your code or scripts, remove them! Of course, as usual, keep your code readable, neat, and most importantly, to your liking. Just keep the lines of code to a minimum.

Lastly, keep your script names shorter. As you can see, the only difference between Test 5 and Test 6, is that Test 6 has a longer ( and more ridiculous ) name. Script names, according to this test, affect their calling speed. It makes sense; long name = long call times. So be sure to shorten the names, but also keep them recognizable, especially if it is an example or engine other users will be working with.

My final words on this would be, keep everything short, sweet, and to the point. It will save your processor some unneeded calculations, and will increase its performance, especially in cases where loops are used often. I hope this helps someone, somewhere! :cool:
  • 5

#2 DanRedux

DanRedux

    GMC Member

  • GMC Member
  • 1404 posts
  • Version:GM:Studio

Posted 08 March 2012 - 05:51 AM

This is until Game Maker is converted to some sort of Byte Code format (which is long overdue). Then silly things like length of names/functions won't matter.
  • 0

#3 kibblesbob

kibblesbob

    "Xarrot Studios"

  • GMC Member
  • 215 posts
  • Version:GM:Studio

Posted 08 March 2012 - 06:42 AM

my face when that happens: :woot:
  • 1

#4 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1819 posts
  • Version:GM:Studio

Posted 17 March 2012 - 05:08 PM

GM's slow scripts have been a well-known fact for a while, as has the solution.

Script name does not affect performance. You are merely putting too much emphasis on an insignificant time difference.

Results of a similar test with 10000000 repetitions: Inline: 9641 ms, Short (sht): 29016 ms, Long (veryverylongscriptnamenoreallyitistoolongforallpracticalpurposes): 29001 ms

Edited by Gamer3D, 17 March 2012 - 05:08 PM.

  • 0
Fast Priority Queues - Game Maker's priority queues are O(n). Mine do everything that Game Maker's do, but in O(log n) time.
Dual-Quaternion Skinning - Modifying vertexes in GM is slow. This simple vertex shader does the job both quickly and well.

#5 kibblesbob

kibblesbob

    "Xarrot Studios"

  • GMC Member
  • 215 posts
  • Version:GM:Studio

Posted 22 March 2012 - 05:00 PM

I've heard of inlining, it's a neat idea. Honestly though, I just tend to use scripts as little as possible anymore :thumbsup:
  • 0

#6 slayer 64

slayer 64

    Slayer of gingers

  • GMC Member
  • 4301 posts
  • Version:GM:Studio

Posted 29 March 2012 - 12:55 AM

make your loop 250 and see if there's a difference in speed
  • 0

5y5rs3d.pngfg0UQNL.png


#7 Desert Dog

Desert Dog

    GMC Member

  • GMC Elder
  • 6409 posts
  • Version:Unknown

Posted 29 March 2012 - 02:18 AM

Give this a test, and see how it compares to your other tests.

script_to_call();
var t;
t = current_time;
repeat ( 25000 )
 { tst(); }
show_message((current_time-t));

tst();
//pick your poison.

Call code:
script_to_call();

  • 0
HTML5 games for mobile:
HexDogs Bugz Burn! Captain George Golfing Block Memory

Games for Androids
*NEW* Word Dog - Published by Dangerous_Dave


Code: General Array Functions - GM-S friendly. sorting, shuffling. Includes a quicksort.
Use the quicksort to sort ds_lists 10-18 times faster than ds_list_sort()!

#8 Yal

Yal

    Even though the GMC may be gone, our love will prevail eternally

  • Global Moderators
  • 11721 posts
  • Version:GM:Studio

Posted 23 April 2012 - 11:36 AM

While it's been known for a long time that Game Maker's scripts are slow, the main reason I try to use scripts as often as possible is because of enhanced readability, and to remove the possibility of overlooking changing code at places.


One vital thing your post didn't make clear: are you using GM8.0 or GM8.1? In GM8.1 scripts were sped up since Game Maker won't pass 16 arguments anymore but only as many as needed. (You'd have to enable an option in the Global Game Settings for this, but it would default be on if you started a new project in GM'81... I think it would default to off if you load an older file, though)
Apparently the main reason the procedure of calling a script itself takes time is because passing the arguments and making room for 16 variables of data takes time, so if that is skipped altogether with argumentless scripts I'd say there should be a less signficant difference between the script and the inline expansion way of doing it.
  • 0

- The above is my personal opinion and in no way representative of Yoyogames or the GMC, except when explicitly stated -

 

Open this spoiler for my games:

Spoiler

Some useful game engines: (all completely free to use, even commercially, as long as you replace all included graphics / music first).
SisterEngine RPG Engine - - YaruFPS 3D Collision Engine -- YaruPlatEngine Platform Engine

New user? Can't draw but want to look unique? You can request a new avatar in this thread!


#9 Desert Dog

Desert Dog

    GMC Member

  • GMC Elder
  • 6409 posts
  • Version:Unknown

Posted 23 April 2012 - 08:48 PM

I use to avoid scripts because 'they were slow', or so I heard. Now I embrace them (or try to!!). It's just smart programming.
  • 0
HTML5 games for mobile:
HexDogs Bugz Burn! Captain George Golfing Block Memory

Games for Androids
*NEW* Word Dog - Published by Dangerous_Dave


Code: General Array Functions - GM-S friendly. sorting, shuffling. Includes a quicksort.
Use the quicksort to sort ds_lists 10-18 times faster than ds_list_sort()!

#10 Yal

Yal

    Even though the GMC may be gone, our love will prevail eternally

  • Global Moderators
  • 11721 posts
  • Version:GM:Studio

Posted 25 April 2012 - 08:16 AM

I realized something... when you need to pass loads of arguments to a script just for the script versatility, couldn't you just use event_perform_object() to call an unused event (e.g. an User Defined Event of a parent object) and save some speed? I'm thinking about making a 2D platformer engine, and to draw the platforms I'd use a script called something like draw_block(x1,y1,z1,x2,y2,z2,sidetexture,fronttexture,toptexture,bottomtexture,siderepeat,frontrepeat,toprepeat,bottomrepeat) which, as you can see, would use a whopping 14 arguments... and practically every single object would call this. Then I got the idea to use the event_user() of some dummy object instead of a script to save the argument passing business (the user event would refer to variables all blocks would have, namely all the things I called the arguments in the script above, rather than to arguments), giving this object "script events" for blocks, cylinders, wedges and so on so that I could make all sorts of platforms from a "blueprint" I could change if need be.
  • 0

- The above is my personal opinion and in no way representative of Yoyogames or the GMC, except when explicitly stated -

 

Open this spoiler for my games:

Spoiler

Some useful game engines: (all completely free to use, even commercially, as long as you replace all included graphics / music first).
SisterEngine RPG Engine - - YaruFPS 3D Collision Engine -- YaruPlatEngine Platform Engine

New user? Can't draw but want to look unique? You can request a new avatar in this thread!


#11 GStick

GStick

    All Secrets Exposed

  • GMC Member
  • 1961 posts
  • Version:GM:Studio

Posted 25 April 2012 - 08:56 PM

^That sounds like a great method for doing something that a large number of objects share. Does it only save on all the annoying argument passing (and repeated code) or has it also improved execution time?
  • 0

Posted Image
The next generation of Game Maker fighting games? More like the best.
Showdown Academy | Showdown Academy Blog


Check out my new album at last.fm: KatazTrophee

#12 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 25640 posts
  • Version:GM:Studio

Posted 25 April 2012 - 09:05 PM

I realized something... when you need to pass loads of arguments to a script just for the script versatility, couldn't you just use event_perform_object() to call an unused event (e.g. an User Defined Event of a parent object) and save some speed? I'm thinking about making a 2D platformer engine, and to draw the platforms I'd use a script called something like draw_block(x1,y1,z1,x2,y2,z2,sidetexture,fronttexture,toptexture,bottomtexture,siderepeat,frontrepeat,toprepeat,bottomrepeat) which, as you can see, would use a whopping 14 arguments... and practically every single object would call this. Then I got the idea to use the event_user() of some dummy object instead of a script to save the argument passing business (the user event would refer to variables all blocks would have, namely all the things I called the arguments in the script above, rather than to arguments), giving this object "script events" for blocks, cylinders, wedges and so on so that I could make all sorts of platforms from a "blueprint" I could change if need be.


You do realise that this is exactly what parenting does? You create a parent object for everything with the code in the draw event and then have everything use event_inherited()... Although I'd still be interested to see what kind of speed differences are involved with using scripts, object holders (as you suggest) and parents, as well as seeing how many instances can be on screen at a time while using these methods...
  • 0

U1FVsm3.png

40799.png


#13 Yal

Yal

    Even though the GMC may be gone, our love will prevail eternally

  • Global Moderators
  • 11721 posts
  • Version:GM:Studio

Posted 26 April 2012 - 08:47 AM

The main idea with an "object holder" (that's a better name) would be that objects that are not childs of some ancestor object call still inherit some "script" from them. For instance in a 3D platformer game you might have blocks with items in that fall off the screen when you hit them, and it'd be nicer to make those draw using an object holder user event than to have to make a parent or duplicate the code for them.

My main plan with the object holders was actually to let both cylinder, wedge and block platforms inherit from one parent, but draw themselves using different sub-events from the parent. That'd be a lot let hassle than having to make an ancestor for each one of them.
  • 0

- The above is my personal opinion and in no way representative of Yoyogames or the GMC, except when explicitly stated -

 

Open this spoiler for my games:

Spoiler

Some useful game engines: (all completely free to use, even commercially, as long as you replace all included graphics / music first).
SisterEngine RPG Engine - - YaruFPS 3D Collision Engine -- YaruPlatEngine Platform Engine

New user? Can't draw but want to look unique? You can request a new avatar in this thread!


#14 Karurosu

Karurosu

    GMC Member

  • GMC Member
  • 218 posts
  • Version:GM:Studio

Posted 17 January 2016 - 04:04 PM

Sorry to revive the topic but, calling scripts its still slower??


  • 0

If you´re reading this, it´s because I´m already dead. So if you want to communicate with my afterlife me,  send an email to: carlosmlg109@gmail.com


#15 grandhighgamer

grandhighgamer

    Village Idiot

  • GMC Member
  • 3875 posts
  • Version:GM:Studio

Posted 18 January 2016 - 12:50 AM

Than having the code in-line? Yes. But you now have the gml_pragma command to force scripts to be compiled inline, as well as the YYC export to compile to actual bytecode and negate a lot of the issues that cause the slowdowns.


  • 1

GHG WUZ ERE


#16 Karurosu

Karurosu

    GMC Member

  • GMC Member
  • 218 posts
  • Version:GM:Studio

Posted 18 January 2016 - 03:07 AM

Than having the code in-line? Yes. But you now have the gml_pragma command to force scripts to be compiled inline, as well as the YYC export to compile to actual bytecode and negate a lot of the issues that cause the slowdowns.


Thanks for the info. But, I was wondering if I can use pragme with a script thats being referrnced in this way "script_execute(variable)"
  • 0

If you´re reading this, it´s because I´m already dead. So if you want to communicate with my afterlife me,  send an email to: carlosmlg109@gmail.com


#17 stainedofmind

stainedofmind

    GMC Member

  • GMC Member
  • 1638 posts
  • Version:GM:Studio

Posted 18 January 2016 - 07:13 PM

Script execution has improved by enormous leaps and bounds since this topic was created, to the point where unless you REALLY need to squeeze every last bit of performance out of your code, it's not worth converting everything to inline.  That being said of course, there is the pragma option as was mentioned.  Personally, all my code is done in scripts and even with some of my performance heavy projects, there's many other things that can be done to optimize.  I don't really think that its worth making my projects rigid to get back a few milliseconds for time...  But that's just me :P

 

Edit:  For giggles, I decided to do a speed test and my results were quite interesting.  I started with what I assumed to be a fairly heavy operation, specifically 'point_distance'.  From that, it showed that executing a script added about an extra 30% of overhead, which scaled pretty well with more repetitions.  Then, for more giggles, I ran it through with something really light, being 'variable = 1 + 2'.  This has scripts taking almost twice as long, again scaling linearly.  THEN!  ...  I tried to come up with the heaviest operation I could think of, in this case 'draw_getpixel'...  And I had to stop the test prematurely because it too WAAAAAAAAAY too long.  After I dropped the number of repetitions down to something more reasonable, the result I got was that the operations were nearly identical in time.  This scaled linearly (again), and even after a 40 second test time, the difference remained the same.  The last test I would do, if I had the motivation, would be a multiple line block of code, but I don't have anything ready to go that would work well here.  I also tried my final test and included passing arguments to the script, but this ironically didn't seem to have any effect on execution time (or very little).  Just a little FYI trivia.  All these tests were done with the VM only.  Don't feel like testing these out on the YYC.


Edited by stainedofmind, 18 January 2016 - 07:41 PM.

  • 1

#18 Karurosu

Karurosu

    GMC Member

  • GMC Member
  • 218 posts
  • Version:GM:Studio

Posted 18 January 2016 - 07:31 PM

Script execution has improved by enormous leaps and bounds since this topic was created, to the point where unless you REALLY need to squeeze every last bit of performance out of your code, it's not worth converting everything to inline.  That being said of course, there is the pragma option as was mentioned.  Personally, all my code is done in scripts and even with some of my performance heavy projects, there's many other things that can be done to optimize.  I don't really think that its worth making my projects rigid to get back a few milliseconds for time...  But that's just me :P

 

refereced script execution delay is an issue in all pl´s... and you should be using the pragma function.. I mean ITS FREE!!


  • 0

If you´re reading this, it´s because I´m already dead. So if you want to communicate with my afterlife me,  send an email to: carlosmlg109@gmail.com


#19 grandhighgamer

grandhighgamer

    Village Idiot

  • GMC Member
  • 3875 posts
  • Version:GM:Studio

Posted 18 January 2016 - 09:26 PM

 

Than having the code in-line? Yes. But you now have the gml_pragma command to force scripts to be compiled inline, as well as the YYC export to compile to actual bytecode and negate a lot of the issues that cause the slowdowns.


Thanks for the info. But, I was wondering if I can use pragme with a script thats being referrnced in this way "script_execute(variable)"

 

 

The entire point of script_execute is to change which script is being referenced at run time. If it can't be precomputed, how is it meant to be inlined? And if you're just using script_execute(scr_my_specific_script); in your code you're just abusing the function.


  • 0

GHG WUZ ERE





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users