Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Performance Counter

Performance Counter
(script for scripterz)


Introduction
This script is useful to mesure little bits of time, more little than with Time class.
You can use it to check if your script is slow and find from which part it comes, or to compare scripts performances.
(I love performance. :fap:)


Script

Ruby:
class PerformanceCounter < Sprite

  QueryPerformanceCounter   = Win32API.new('kernel32', 'QueryPerformanceCounter'  , 'p', 'i')

  QueryPerformanceFrequency = Win32API.new('kernel32', 'QueryPerformanceFrequency', 'p', 'i')

  QueryPerformanceFrequency.call(buf = "\0"*8)

  @@frequency = buf.unpack('Q')[0].to_f

  QueryPerformanceCounter.call(a="\0"*8)

  QueryPerformanceCounter.call(b="\0"*8)

  @@offset = b.unpack('Q')[0] - a.unpack('Q')[0]

  attr_accessor :display_type, :refresh_rate

  def initialize(display_type=0, refresh_rate=1)

    super()

    self.z, self.bitmap = 0x7FFFFFFF, Bitmap.new(200,20)

    bitmap.font.color.set(255,255,0)

    @a,@b,@t,@display_type,@refresh_rate = "\0"*8,"\0"*8,-1,display_type,refresh_rate

  end

  def refresh

    i = @b.unpack('Q')[0] - @a.unpack('Q')[0] - @@offset

    @t = i if @refresh_rate==0 ? @t<0 || @t>i : Graphics.frame_count%@refresh_rate==0

    bitmap.clear

    bitmap.draw_text(bitmap.rect, case @display_type

                                  when 1; "%.3f ns" % ns

                                  when 2; "%.3f µs" % us

                                  when 3; "%.3f ms" % ms

                                  when 4; "%.3f s"  % s

                                  else    @t.to_s

                                  end)

  end

  def a()  QueryPerformanceCounter.call(@a) end

  def b()  QueryPerformanceCounter.call(@b)

           refresh                          end

  def c()  a; yield; b                      end

  def t()  @t                               end

  def ns() @t * 1000000000 / @@frequency    end

  def us() @t * 1000000 / @@frequency       end

  def ms() @t * 1000 / @@frequency          end

  def s()  @t / @@frequency                 end

end

Instructions
First create a counter :
$pc = PerformanceCounter.new

Then place the tags on both sides of what you want to mesure, like this :
$pc.a
do_something
$pc.b

Or by using a block like that :
$pc.c {do_something}

The counter is a Sprite (so you can place it where you want with x and y methods) and is automaticaly refreshed, you just have to place the tags.
You can choose the way the time is displayed and at what rate it's refreshed on the initialization :
$pc = PerformanceCounter.new(display_type, refresh_rate)

Or after by using the accessors :
$pc.display_type = x
$pc.refresh_rate = y

There are 5 differents display_type : 0 = number of ticks*, 1 = nanoseconds, 2 = microseconds, 3 = milliseconds and 4 = seconds (default is 0).
For the refresh_rate it's a number of frames, but if you set it to 0 it will only keep the lowest value, if you have a code that is not dynamic it may give a result nearest of the reality (default is 1).
And if you want you can get the last time in ticks*, nanoseconds, etc... with $pc.t, $pc.ns, $pc.us, $pc.ms or $pc.s


*Or cycles perhaps ? I'm not sure, it's an unit which is processor relative but too high I think to be one of this kind.
On my PhenomII X4 4Ghz, 1 unit is equal to 255 ns. :(
 
The performance encounter itself consumes a bit too much resources to keep things accurate.

Although anything is going to use some resources, something that is used to benchmark speed should be as low impact as possible. I've personally really only tested methods, calls, with the Console Debug script I wrote.

At the beginning of the method, place a "start = Time.now.to_f" and at the end place a "puts (Time.now.to_f - start)"
This will output the time the call took to execute, and of course you can edit it a bit to output averages, etc.
 
im with foreverzer0 i always just use

time=Time.now
my code
p Time.now-time

but im glad im not the only one that likes to measure the speed of my code :D
 
If you look at the code you'll see that between the markers there is nothing except the call of the Api which pick the time, the refresh of the bitmap is done after #b so it doesn't impact the time at all.
The call to the Api is quite fast (1.2 µs), but if it can make you happy I edited the script to remove it (even if it's not perfect).
And why not use Time.now ? Well in RM we use Ruby 1.8.1 and its Time class can't go under milliseconds.
So it avoid doing :
time=Time.now
10000.times {my code}
p Time.now-time

But the most interesting in this script I think is that you can use it with ease and all is displayed on the flow. :)
 
i dont think you need to go that deep with ruby, but thats just a personal opinion, i only go super deep with my c# programs, because i might actually be able to make them run fast :P silly slow ruby :) but i do see your point, to each their own.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top