Hamsterspeak runtime cost

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

Post Reply
User avatar
DWRL
Red Slime
Posts: 35
Joined: Wed Jan 15, 2020 2:26 am
Location: Germany
Contact:

Hamsterspeak runtime cost

Post by DWRL »

HamsterSpeak has no List-Comparison, e.g. in Python:

Code: Select all

if x in list:
Of course, one could use if or switch/case, but is there a point upon which those drag the engine down?
For example, limit text entry to certain character, lets say only alphanumericals, would mean putting each entry through a switch/case with 61 branches...

I have no problem doing that, but I fear it might impede performance.
Last edited by DWRL on Wed Mar 10, 2021 8:09 pm, edited 1 time in total.
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7684
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

Don't worry about big lists of cases in a switch block, the performance of those is quite good. I have this in one of my scripts:

Code: Select all

script, get monster create callback, id, begin
  # Also creates items that you can pick-up
  variable(cb)
  cb := 0
  switch(id) do(
    case(1) do(cb := @create cactus golem)
    case(2) do(cb := @create carrot demon)
    case(3) do(cb := @create pounce rose)
    case(4) do(cb := @create spark effect)
    case(5) do(cb := @create butterhawk)
    case(6) do(cb := @create prancing bulb)
    case(7) do(cb := @create prancing flower)
    case(8) do(cb := @create death tulip root)
    case(9) do(cb := @create death tulip flower)
    case(10) do(cb := @create machete item)
    case(11) do(cb := @create caterpillar)
    case(12) do(cb := @create mace dryad)
    case(13) do(cb := @create plummet bell)
    case(14) do(cb := @create leaping amaranth)
    case(15) do(cb := @create save point)
    case(16) do(cb := @create sunflower golem)
    case(17) do(cb := @create spigot wad)
    case(18) do(cb := @create droplet source)
    case(19) do(cb := @create bramblespitter)
    case(20) do(cb := @create toadstool knight)
    case(21) do(cb := @create creeping bellflower)
    case(22) do(cb := @create mycelium bridge breaker)
    case(23) do(cb := @create ghost orchid legs)
    case(24) do(cb := @create mushroom pop agent)
    case(25) do(cb := @create hedge bunny)
    case(26) do(cb := @create simple spike)
    case(27) do(cb := @create rose hip)
    case(28) do(cb := @create pressure plate)
    case(29) do(cb := @create living abacus item)
    case(30) do(cb := @create randomizer sigil item)
    case(31) do(cb := @create purple pounce rose)
    case(32) do(cb := @create pruning shears item)
    case(33) do(cb := @create shop door agent)
    case(34) do(cb := @create prickly lettuce)
    case(35) do(cb := @create inverse larkspur)
    case(36) do(cb := @create green knight)
    case(37) do(cb := @create necros root)
    case(38) do(cb := @create heli succulent)
    case(39) do(cb := @create key item)
    case(40) do(cb := @create piece of heart)
    case(41) do(cb := @create labyrinth gate agent)
    case(42) do(cb := @create bullrusher)
    case(43) do(cb := @create bullrusher gate agent)
    case(44) do(cb := @create corpse eater)
    case(45) do(cb := @create bursting cactus)
    case(46) do(cb := @create breakwall agent)
    case(47) do(cb := @create millipede head)
    case(48) do(cb := @create millipede body)
    case(49) do(cb := @create killall break agent)
    case(50) do(cb := @create creeping petunia)
    case(51) do(cb := @create least frogmuculus)
    case(52) do(cb := @create omen caster)
    case(53) do(cb := @create carrot diablo)
    case(54) do(cb := @create papyrus map item)
    case(55) do(cb := @create map1 item)
    case(56) do(cb := @create map2 item)
    case(57) do(cb := @create map3 item)
    case(58) do(cb := @create map4 item)
    case(59) do(cb := @create flame vine)
    case(60) do(cb := @create letter)
    case(61) do(cb := @create green pixy)
    case(62) do(cb := @create colobanthus)
    case(63) do(cb := @create twigbrush)
    case(64) do(cb := @create bubble maker)
    case(65) do(cb := @create puncher sigil item)
    case(66) do(cb := @create frost blossom)
  )
  exit returning(cb)
end

however, specifically for limiting characters to alphanumericals, you can probably make something that is more short and readable, since the alphanumerical characters are all located within a few ranges, so a couple >= and <= checks is going to work well for that

Are you wanting to filter by ascii code of the character? or by scan code of the keyboard key?
TMC
Metal King Slime
Posts: 4310
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

'switch' is implemented by checking each case one at a time (not with a lookup table like C compilers might use), but is a lot faster than an equivalent elseif chain. I've never timed it.

But in the example you gave performance is irrelevant, because the switch only gets run once for each key the player presses. CPUs can perform billions of instructions per second and the implications of that are very unintuitive!

I don't know what that has to do with for-each loops.
User avatar
DWRL
Red Slime
Posts: 35
Joined: Wed Jan 15, 2020 2:26 am
Location: Germany
Contact:

Post by DWRL »

TMC wrote:I don't know what that has to do with for-each loops.
Uhm, nothing, I just wrote an example for a list-comparison without thinking too much. I was on lunch-break... :hurr:
TMC wrote:CPUs can perform billions of instructions per second (...)
My fears are more about limits in the script-execution itself, I know it is compiled (into what...? And is it than still technically a 'script'?), and the code should be through in one tick, but since I really do not know, I figured I better ask :D
Bob the Hamster wrote: Don't worry (...), I have this in one of my scripts:
Yes, that actually puts me quite at ease :v:

The text-input usecase was just an example I knew will become relevant shortly, so I actually haven't decided on implementation, but you are right, some short comparisons will do nicely.
But there will be more situations like that similar to your example (which fight to start? which dialog to show etc).

Thank you both :)
TMC
Metal King Slime
Posts: 4310
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

You should only worry about parts of your scripts that will run tens of thousands of times or more (or call script commands which might be slow). As a rule of thumb, interpreted languages like HS, Python and Ruby tend to be roughly 100x (let's say 100-1000x) slower than compiled ones like C. So assuming a fast modern CPU (~10 billion instructions a second) assume your script can do roughly 10 to 100 million primitive operations per second. But you have to divide that by your framerate to know how much you can do each frame.

Oh wait, I do have benchmarks of switch speed. Looks like it takes about 20 nanoseconds per 'case' check. (Over 5x faster than an elseif!) So 50 million per second.

EDIT: I looked at the implemention of 'switch' and it was trivial to speed it up another ~10%.
Last edited by TMC on Thu Mar 11, 2021 12:59 am, edited 3 times in total.
Post Reply