Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411430 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 20, 2024, 02:19:46 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)TutorialsGame Maker: Optimizing For Speed/Memory
Pages: 1 [2] 3
Print
Author Topic: Game Maker: Optimizing For Speed/Memory  (Read 122745 times)
Gnarf
Guest
« Reply #20 on: November 26, 2008, 06:31:38 PM »

Code: (Xot, via GMC)
// SLOW
for (i=0; i<10; i+=1) array[i] = random(100);

// FASTER
i = 0;
while (i < 10) {
   array[i] = random(100);
   i += 1;
}

// EVEN FASTER
i = 0
repeat (10) {
   array[i] = random(100);
   i += 1;
}

// FASTEST
array[0] = random(100);
array[1] = random(100);
array[2] = random(100);
array[3] = random(100);
array[4] = random(100);
array[5] = random(100);
array[6] = random(100);
array[7] = random(100);
array[8] = random(100);
array[9] = random(100);

I link to where that is from would be awesome. The fastest one make sense, but the others, and the "even faster" one in particular, sound very strange.
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #21 on: November 26, 2008, 06:33:09 PM »

I think it's from the gmc thread I linked to earlier.
Logged

ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #22 on: November 26, 2008, 06:59:25 PM »

Another tip: it's sometimes faster to use your own collision checking than to use GM's, although it's sometimes slower too. TeeGee did an experiment, and if you want basic circle collisions, you can use something like 'with(obj_type) if point_distance(x, y, other.x, other.y) < 40 then collision(id, other.id);' And that would usually work faster than GM's collision detection, unless the number of objects you're checking collisions for is in the hundreds, in which case GM's system is faster.

With or without custom collision checking, you can speed up collisions by checking for them only one of the two colliding objects, and use the one with fewer instances. For instance, if you want to check for collisions between bullets and enemies, check for that collision in the bullet if there are usually fewer bullets on screen than enemies on screen, and check for that collision in the enemy if there are usually fewer enemies on screen than bullets on screen.
Logged

Gnarf
Guest
« Reply #23 on: November 26, 2008, 07:19:27 PM »

I think it's from the gmc thread I linked to earlier.

I don't have permission to search the topic because I'm not logged in. If I get a blog some day I'm so totally going to rant about forums that do that kind of thing! Rarr.

Anyway. Thanks, I found it. And it doesn't explain anything. And that is the kind of thing I wouldn't do unless I understood why it was faster*. Now, there are possible reasons why repeat might be a faster loop, but I wouldn't assume that to still be the case if you're increasing a variable like that every iteration anyway.

It just sounds like there's a good chance of people adopting some really bizarre habits after reading posts where someone misunderstood what someone else said in a post where they did some really imprecise tests of something that never ever mattered.

* Well. I really wouldn't do any kind of optimization without knowing what I was doing and why it mattered.
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #24 on: November 26, 2008, 07:22:13 PM »

Unwinding loops is faster in GM for the same reason it's faster in all programming languages. See this for some discussion on it: http://en.wikipedia.org/wiki/Loop_unwinding

Also if you count the number of instructions for each of the examples, the number of instructions to the CPU goes gradually down with each.
Logged

Gnarf
Guest
« Reply #25 on: November 26, 2008, 09:09:22 PM »

Unwinding loops is faster in GM for the same reason it's faster in all programming languages. See this for some discussion on it: http://en.wikipedia.org/wiki/Loop_unwinding

Yes. I know why unwinding loops can be faster. Which is why I said that the fastest one made sense.

Also if you count the number of instructions for each of the examples, the number of instructions to the CPU goes gradually down with each.

No. There are no CPU instructions in the examples. You can count GML statements.

There's no reason to assume that the while and the for examples translate into different sets of instructions.

There's every reason to assume that "repeat (10)" results in instructions for setting some integer's initial value, and then increasing/decreasing it and checking its value every iteration of the loop. I'd say the most reasonable assumption would be that "repeat (10) {}" and "for (i = 10; i < 10; i += 1) {}" would both translate into mostly equivalent instructions and the same number of instructions. There are some possible reasons why repeat would translate into something faster, if the GML compiler was particularly clever about optimizing repeat loops. But then you'd have to add in the "i += 1" in the block statement, while in the 'for' and 'while' examples the variable that is being used for looping can also be used as index for the array. The reasonable assumption would be that the repeat example is slower.

In super-short, there's no "do this n times" CPU instruction. GML statements that do more stuff translate into more CPU instructions, as a general thing.
« Last Edit: November 26, 2008, 09:24:01 PM by Gnarf » Logged
Derek
Bastich
Administrator
Level 10
******



View Profile WWW
« Reply #26 on: November 26, 2008, 10:25:56 PM »

It was corroborated somewhere else by someone who tested all the different loops and found out that repeat was the fastest and for was the slowest.  But the link was gone and I can't find the thread atm.  I'll take it off the list until it makes sense.
Logged
Pishtaco
Level 10
*****


View Profile WWW
« Reply #27 on: November 27, 2008, 03:39:18 AM »

I think vsync does work, in that it keeps you in synch with the screen's refresh cycle. It just seems to put you at the wrong place in the cycle. But it can still be made to work -- see the other thread: http://forums.tigsource.com/index.php?topic=3711.msg109620#msg109620
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #28 on: November 27, 2008, 03:57:12 AM »

Code: (Xot, via GMC)
// SLOW
for (i=0; i<10; i+=1) array[i] = random(100);

// FASTER
i = 0;
while (i < 10) {
   array[i] = random(100);
   i += 1;
}
Yes, it fascinates me that GM could make one of these slower than another. Even in uncompiled scripted languages, I fail to see how there could be any difference. repeat(10) could conceivably be faster though, and loop unrolling is clearly faster.
I presume it's faster for the same reason adding in blocks ( { } ) is slower, not that I can see any reason for that, either.

This tutorial needs a final bullet point mentioning if speed is really a concern, you should consider simply not using Game Maker. It is orders of magnitude slower than other environments.
Logged
Jolli
Guest
« Reply #29 on: November 27, 2008, 10:54:10 PM »

Quote
This tutorial needs a final bullet point mentioning if speed is really a concern, you should consider simply not using Game Maker
Well, hello there! o ur sooo funny
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #30 on: November 28, 2008, 04:38:22 AM »

It's slower in that it's an interpreted language, but in other ways it's just about as fast as anything using DirectX 8. The drawing itself is just as fast I mean, it's the interpretation of the code that slows it down. Python, QBASIC, and other interpreted languages have the same problem.
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #31 on: November 28, 2008, 06:28:02 AM »

I didn't mean the speed thing as a joke or flippant remark. GM has many things going for it, such as ease of development, and an extensive library of useful game related commands and scripts. But choosing your starting environment is an important part of making a game, so you do have to at least consider the question of whether the speed issue is going to cause problems or not.

I have not done any empirical tests, but anecdotal evidence supports GM scripts are slower than most other interpreted languages. With regards to scripts, most interpreted languages are "compiled" to bytecode nowadays and/or involve JIT compilation. GM doesn't seem to, as evidenced by the rather odd circumstances that can cause a script to run slower, which suggest it is re-interpreting the text every time it comes to a line.

I could go on about other aspects of this speed guide that I've read and have caused major "WTF"s, but I'd just be ranting.
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #32 on: November 28, 2008, 06:38:05 AM »

GM is in fact compiled to bytecode I believe. It doesn't use JIT compilation, though.

I think a lot of the optimization strategies in Derek's guide would also apply even to compiled languages. Unrolling loops helps even in C++. Drawing primitives or text to a surface and then using that surface rather than re-calculating that every step also helps in any language, compiled or interpreted.
Logged

Alex May
...is probably drunk right now.
Level 10
*


hen hao wan


View Profile WWW
« Reply #33 on: November 28, 2008, 07:10:42 AM »

It is desirable to optimise within one's familiar environment rather than to migrate to a new one where mistakes could be made due to inexperience that cause more problems than the potential speed increase gains the developer. Add to that the time required to migrate the game, and learn the new environment and language, and it ends up being a fairly pointless remark IMO.

That said, at the start of a project, if the estimate of the game's processing usage is known to be likely to stretch GM, it could be time for the developer to learn a more flexible game making environment.
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #34 on: November 28, 2008, 02:37:10 PM »

That said, at the start of a project, if the estimate of the game's processing usage is known to be likely to stretch GM, it could be time for the developer to learn a more flexible game making environment.
Yes, exactly. And as you say, intimate knowledge of a language is always a strong factor in your decisions as well. This is why I was careful to highlight that it's only an issue if speed is of major importance in your game.

BUT, while most of the optimizations make sense, and are the same across all languages and platforms, you have to admit some of the answers at the top smell a bit dodgy? 50 instances max? Sample down music? "Collision functions (and trig calculations) in general are pretty heavy"? I'm sure it's good advice, but you have to question why?

Just to double check I'm not crazy, I did some simple bench marking on my machine (Vista 32bit 2GHz dual core). Obviously the usual caveats apply that I only did one run, and I am only looking at one very specific test. I also re-ran the Javascript test, as the first result was done in Firebug, and evidently was some debugging mode compared as it took 87 seconds.
GML (Game Maker 7):
Code:
t1 = current_time
repeat(10000){
    a=1
    i=0
    while(i<5000){
        a+=i
        i+=1
    }
}
t2 = current_time
show_message(string(t2-t1))
66.969 seconds

Python (CPython 2.5.2):
Code:
from time import clock
t1=clock()
for j in xrange(10000):
    a=1
    i=0
    while(i<5000):
        a+=i
        i+=1
t2=clock()
print (t2-t1),"seconds"
25.159 seconds

Javascript (Firefox 3.0):
Code:
var t1 = new Date();
for(var j=0;j<10000;j++){
    a=1;
    i=0;
    while(i<5000){
        a+=i;
        i+=1;
    }
}
var t2 = new Date();
alert(t2-t1)
27.569 seconds

Actionscript 3 (Adobe Flash):
Code:
var t1 = getTimer();
for(var j=0;j<10000;j++){
    var a = 1;
    var i = 0;
    while(i<5000){
        a+=i;
        i+=1;
    }
}
var t2 = getTimer();
trace(t2-t1)
7.644 seconds

Actionscript 3 (typed) (Adobe Flash):
Code:
var t1:Number = getTimer();
for(var j:int=0;j<10000;j++){
    var a:Number = 1;
    var i:int = 0;
    while(i<5000){
        a+=i+Math.random();
        i+=1;
    }
}
var t2:Number = getTimer();
trace(t2-t1)
10.021 seconds
Note I had to add extra work into this code to force it to run every line. Without that, it ran in 399ms, which I suspect is more to do with compiler optimizations than anything else. So AS3 is actually blindingly fast, compared with other scripting languages.

VBScript (Windows Scripting Host):
Code:
t1 = Timer
For j=1 to 10000
    a=1
    i=0
    do while i<5000
        a = a + i
        i = i + 1
    loop
Next
t2 = Timer
MsgBox t2-t1
87.60938 seconds

So make of that what you will, I was certainly surprised.
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #35 on: November 28, 2008, 07:34:01 PM »

I think 50 instances is an exaggeration. Immortal Defense used 400+ instances at once with no slowdown on most modern computers. It depends on how you code it, I suspect that if most of the instances are doing collision checks, you have to do with fewer, but if most of them are coded well enough and don't do collision checks, you can "get away" with several hundred.

Lowering the sampling rate of music is not really a good optimization, I don't agree with it. I suggest just streaming music from the hard drive using a sound dll like fmod, don't load all the music into memory at once, or even all of a single track.
Logged

ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #36 on: November 28, 2008, 07:35:45 PM »

But thanks for that test, it's interesting. Still, that's fifty million loops a minute, which is far more than most games would ever need, so the difference may seem like a lot there, but in practice there'd be very little difference because the game would run at the same frame rate as it would in other languages, it'd just use twice as much CPU.
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #37 on: November 29, 2008, 05:06:10 AM »

I chose 50000000 loops to get rid of start and end overhead, at max CPU usage. And those took 60 seconds to run. If you wanted a 60fps game, that comes down to 14,000 loops per frame. And these were the barest entry loops you could get. If you were, say, calculating distances between shapes, and doing every pair, I estimate that each loop would be at least 10 times slower, which means you could manage about 40 objects before crapping up, and thats without running other stuff in the same frame.

Of course, that's again a poor example, particularly as GM has built in collision detection, and loops over instances more efficiently (probably), and no sane person would do brute force pairing, but it is at least shows that the sorts of speeds we are talking about make a tangible difference to games, at least if you are doing AI, physics, path finding, or any other computationally heavy chore.

I think I could design reasonable games that would require that level of calculation. How many RTS games do you see made in Game Maker (present company excepted).
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #38 on: November 29, 2008, 08:27:27 AM »

Still, I know from experience that I can get 60 fps with AI and hundreds of objects (such as in my current game Saturated Dreamers), each with their own coded collision detection, as long as each isn't very code-intensive, so I think the estimates of "don't use more than a few dozen objects" are exaggerated. But I agree that you have a point, if you aren't prepared to adjust your game to some degree in order to optimize it, you shouldn't use GM, but I would still estimate that GM can make about 99% of 2D games that you can make in other languages without any significant changes or optimizations or sacrifices. But I agree that it probably wouldn't work as well for games like, say, Starcraft, where you need hundreds or even thousands of units, each with their own unique AI and pathfinding, and can't afford to turn units off when they're outside of the view because they need to remain active at all times.

I've seen about five RTS games made in GM, more than 10 if you count tower defense games as RTS games. I'm sure there are many more. The best RTS's were the Jeluvian Project and Dark Hive, one of which were in my 100 Game Maker Games in 10 Minutes video if you want to take a look at them. I couldn't get Dark Hive to record correctly with FRAPs or CamStudio though, or I would have included it too.
Logged

Zaphos
Guest
« Reply #39 on: November 29, 2008, 04:41:42 PM »

Things really do add up if you have a nested loop or a big 2D or 3D data structure.  14,000 sounds like a large number, but if you take the square root, it's just ~118, so if you're planning to (for example) do some graphical effect on a per pixel basis, you'll get a pretty hard limit on how large that graphical effect can be.  So that does mean there are some sorts of algorithms which just won't work.  Like ... don't try to implement your game logic as a giant cellular automaton ...
Logged
Pages: 1 [2] 3
Print
Jump to:  

Theme orange-lt created by panic