Input.press?(:UP) faster than blank method???

??????

Diabolical Codemaster
Veteran
Joined
May 11, 2012
Messages
6,513
Reaction score
3,203
First Language
Binary
Primarily Uses
RMMZ
Hey,

So recently I began rewriting a keyboard/mouse input system of mine due to discovering how inefficient it was, anyway, during this process,  began to ensure my methods where faster than the default methods - or at least as quick...

First of all, I loaded / inserted the benchmarking script into my project.

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html

Secondly, I made a small test like so...

module Input  def self.blankmethod(aarrgg)  endendLOOPS = 500_000Benchmark.bm do |x|   p "Input.test = "  x.report { LOOPS.times { Input.press?:)UP) } }  p "Blank.test = "  x.report { LOOPS.times { Input.blankmethod:)UP) } } endThird - I hit play and viewed the results...

( user ) , ( system ) , ( total ) , ( real )Input.test = 0.109000 , 0.000000 , 0.109000 , 0.111007Blank.test = 0.140000 , 0.000000 , 0.140000 , 0.133007Now as you can see, to call a Input.blank method 500,000 times takes longer than calling Input.press?(buttonsymbol) (the same amount of times) does.

I mean, how is that possible?

How is one supposed to write a script that is just as / more efficient when I cannot even create a blank method that processes quicker? Anyone have any ideas on that?

So far I have managed to get my Input.update method running around 3-4x faster than normal input.update, but imo, the press and trigger methods are just as/more important in the long term goal of efficiency.

I guess I am just not able to comprehend how the press method runs faster than a blank method does. I mean, if press? was just calling pure C/C++ code then yea, i could understand, but if that was the case why is the input.update method dramatically inefficient. ?
 
Last edited by a moderator:

Another Fen

Veteran
Veteran
Joined
Jan 23, 2013
Messages
564
Reaction score
275
First Language
German
Primarily Uses
I don't know for sure, but as far as I remember that some specific methods are handled different from the regular ones. For example Array#[] is not executed as a regular method by default and therefore a bit faster in execution (does not work for subclasses of Array when I remember correctly).

I could neither find the source of that statement again nor am I aware how the ruby interpreter processes method calls in the first place, so if anyone knows about the details I'd love to hear them. :)
 
Last edited by a moderator:

FenixFyreX

Fire Deity
Veteran
Joined
Mar 1, 2012
Messages
434
Reaction score
310
First Language
English
Primarily Uses
The fact that Input::press? is written in C is alone enough to make it faster than a blank Ruby method, so there's that.


EDIT: In fat, it's wise to remember that almost all methods like Input::press?, Audio, Graphics, etc are written in C, then exposed to Ruby via Ruby's C API. Ruby will never be as fast as the language it's written in, because of interpretation overhead, internal type checking, extra pointer arithmetic (from VALUEs in C to Objects in Ruby) and many more things. Unless you write the method in C and expose it to Ruby, it won't be as fast.


That being said, most things, when called through a dll, are faster than the de facto methods Enterbrain has provided us, apparently because they only exercised minimal optimization on all of their code. This is seen when we take a Tilemap and pair it with a Resolution breaker, or an Input script with an FPS delimiter script.
 
Last edited by a moderator:

cremnophobia

Veteran
Veteran
Joined
Dec 10, 2013
Messages
216
Reaction score
97
Primarily Uses
1. Loop counter is too low.

2. I can't reproduce the result at all. Was this your only try and did you reverse the two tests?

3. Most importantly: you're using benchmark and not benchmark-ips:

Benchmark.ips do |x| x.report('Input.test = ') { Input.press?:)UP) } x.report('Blank.test = ') { Input.blankmethod:)UP) }end
Code:
Calculating -------------------------------------       Input.test =      48149 i/100ms       Blank.test =      50717 i/100ms-------------------------------------------------       Input.test =   2676286.0 (±2.4%) i/s -   13385422 in   5.004277s       Blank.test =   2861435.4 (±2.9%) i/s -   14302194 in   5.002288s
Kinda pointless. One big performance gain is to prevent object allocation, but (at least in a legal way) it's unlikely to be able make your own methods (that actually do the same stuff) as fast as the original ones. And ask yourself, does speed actually matter in this case? Drawable objects are  another big issue.
I could neither find the source of that statement again nor am I aware how the ruby interpreter processes method calls in the first place, so if anyone knows about the details I'd love to hear them. :)
In RGSS3 Ruby is compiled to bytecode. To get an textual representation of it, see the disassemble methods. And yes, I know that I've linked to 2.1.3 and not to 1.9.2, because they were undocumented back then, but there isn't much difference - the bytecode and the output may differ, but that's not important now.To read the C implementation of the bytecode instructions, read insns.def. For Array#[] or Hash#[] see opt_aref (line 1876 to 1904). If you scroll up or down, you'll see other optimized instructions. Of course, redefining such methods cancels the performance gain.
 
Last edited by a moderator:

BigEd781

undefined method 'stupid_title' found for nil:NilC
Veteran
Joined
Mar 1, 2012
Messages
940
Reaction score
304
First Language
Dothraki
Primarily Uses
N/A
The fact that Input::press? is written in C is alone enough to make it faster than a blank Ruby method, so there's that.
 
That doesn't add up.  It's not like it's inlined C.  You still have the overhead of the ruby method call in both cases. The only difference is that one does nothing, the other does something. Since doing nothing is always faster than doing something, the empty method should be faster.


That said, the Ruby interpreter is not exactly built for performance.  The overhead of the loop itself is probably significant in such a contrived performance test.  The actual code being called is probably in the noise, i.e., the loop overhead and method call comprise N% of the CPU time, where N is significant.  You also need to realize that context switches occur, so perhaps your torrent downloading in the background interrupted the dummy method call a few times, hence the slightly longer run time.  All sorts of things can affect performance profiles, especially when you're attempting to measure something that takes so little time.


Contrived tests like these don't mean much of anything, and that method call is never going to be a bottleneck.  Measuring performance is non-trivial and nuanced.  You need to understand what is going on behind the scenes in order to make sense of the results.
 
Last edited by a moderator:

??????

Diabolical Codemaster
Veteran
Joined
May 11, 2012
Messages
6,513
Reaction score
3,203
First Language
Binary
Primarily Uses
RMMZ
@Tsukihime

Yep, done that. Each test yields similar results.

@Another Yen

Yes this is quite likely. A lot of ruby methods just trigger some C/C++ code directly. So yea, it would make sense that making a child of array would not be as quick as array as your child class is likely going to be altering methods somewhere (otherwise what is the need for an array child?) and subsequently, ruby code is being added which has to then be interpreted. :)

@FenixFyreX

Yea, that is the only thing I can come up with for how the method is so quick!

Trust me, we dont even want to get into how the dir4 and dir8 methods are EVEN FASTER!...

What I dont get though, is why the update method is so slow. If the Input is all written in C/C++, surely they would have made the update method - the only one that is intended to be called each and every frame - faster than the others?

I mean, my update method is MUCH faster than the default method - if I can make that faster, why not the others..

I have figured that the only way to actually beat the speed is to write up a dll that adds ruby methods into the engine that when called, call some C code directly. - Still a while to go on that one.. I'm at the process of figuring out how to make my dll attach onto the engine and then I will be trying to figure out how to add ruby methods into the engine directly from my dll.

For a Ruby input script though, mine is running faster than those currently tested against (except the default one of course). I am currently downloading as many as I can find to test against. :D

@cremnophobia

I have also tested on a 2,500,000 loop check with the blank method again, taking longer.

Wasn't aware of that Benchmarking util. Gonna get the pieces together and test it out later, thanks for linking it :)

Yea, the Input's speed may not be the biggest of concerns and honestly, it wasnt until I realized how inefficient my old input script was. (took 135 secs for 100,000 update loops - yes, really poorly written). Now I have accepted that I wont be able to beat the input's normal speed without writing up a dll. - Currently processing various ideas on how I could do such a thing with my current  level of C++ knowledge but uhh... yea...

@BigEd

Yea, my thinking was also that "doing nothing has to be faster than doing something" but evidently, that is not the case here... (worryingly, the dir4 and dir8 methods are even faster (quite a bit) than the press? method.)

I did test the performance of various loop types as well to ensure that my chosen loop was 'the quickest' - was very close but overall, seemed that N.times was the route to go :p

As far as torrents etc, I have tested this whilst my computer had nothing else running - at all. Just RPG maker and the bare essentials, no media or internet connection or anything like that. the tests all show that doing nothing actually takes more time than doing something :D
 

BigEd781

undefined method 'stupid_title' found for nil:NilC
Veteran
Joined
Mar 1, 2012
Messages
940
Reaction score
304
First Language
Dothraki
Primarily Uses
N/A
@BigEd

Yea, my thinking was also that "doing nothing has to be faster than doing something" but evidently, that is not the case here... (worryingly, the dir4 and dir8 methods are even faster (quite a bit) than the press? method.)

I did test the performance of various loop types as well to ensure that my chosen loop was 'the quickest' - was very close but overall, seemed that N.times was the route to go :p

As far as torrents etc, I have tested this whilst my computer had nothing else running - at all. Just RPG maker and the bare essentials, no media or internet connection or anything like that. the tests all show that doing nothing actually takes more time than doing something :D
My point was that you're not measuring what you think you're measuring.  There is error in every measurement, caused by any number of unpredictable events occurring in your system.  If the thing that you are trying to measure is so fast that it comprises a statistically insignificant amount of the total CPU time then you end up measuring the error and really nothing else. You can be confident in the fact that doing nothing is faster than doing something.  That is a given.  Now, since I have to guess at what is causing the small discrepancy, I have guessed that it is caused by the reasons that I have previously stated.  I could be wrong, I'd have to do more work to convince myself of it.  Again though... an empty method call is not slower than a method call which does *anything* other than nothing.
 

??????

Diabolical Codemaster
Veteran
Joined
May 11, 2012
Messages
6,513
Reaction score
3,203
First Language
Binary
Primarily Uses
RMMZ
Yea I see what your getting at now. Never really thought of it like that but i guess its a pretty accurate way to see things. :)

I guess I will just have to be satisfied with 'the most efficient ruby input script'. Really, my methods are showing that 'overall', my input method is more efficient (but i assume thats just from the way it was tested (doing input.update and input.press checks in the same method and testing those speeds) ).. Really though, yea, the amount of cpu thats being used is nothing compared to some other things.

I just want to make sure my input system is as efficient as possible as its one of the few systems I use in all my projects. :D
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,865
Messages
1,017,059
Members
137,574
Latest member
nikisknight
Top