Forum Discussion

Romans_I_XVI's avatar
Romans_I_XVI
Roku Guru
11 years ago

Can you make this code more efficient?

Hi, I am attempting to make my netcode as efficient as possible. It is being used to update the state of each player in game. Here is what I'm currently doing.


While this.udp.isReadable()
received = this.udp.receive(this.buffer, 0, 20)
if received > 0
params = {}
params.id = resolve_two_byte_integer(this.buffer[12],this.buffer[13])
params.x = resolve_two_byte_integer(this.buffer[14],this.buffer[15])
params.y = resolve_two_byte_integer(this.buffer[16],this.buffer[17])
params.color = this.buffer[18]
params.destroy = this.buffer[19]
id_exists = false
for a = 0 to this.players.Count()-1
if this.players[a].id = params.id
this.players[a].x = params.x
this.players[a].y = params.y
if params.destroy = 1
print "Removed player - id : " ; this.players[a].id
this.players[a].sprite.Remove()
this.players.Delete(a)
end if
id_exists = true
exit for
end if
end for
if not id_exists
params.sprite = this.compositor.NewSprite(270, 500, this.region_ring[params.color])
params.sprite.SetData(params.id)
this.players.Push(params)
end if
end if
End While


And here is the "resolve_two_byte_integer()" function

Function resolve_two_byte_integer(byte_a, byte_b)
value = byte_a + (byte_b * 256)
return value
End Function


It currently takes 20-40ms with 20 active players using Roku 1 (slowest device I have). I know odds are there won't even be this many players, but I'd like to just make sure I have it as efficient as possible.

Thanks!

3 Replies

  • While I haven't timed any brightscript for my own applications, just a scan of your code would lead me to target a few things.


    • Does udp.receive take a long time? How about receiving a large block (20*20=400) and looping over it so you only have to read from the network once

    • Does object construction take a long time? Move 'params = {}' out of your loop and reuse it.

    • Do you have to walk the player array for every update that comes in? Perhaps players should be an associative array where the key is 'id'. Then most likely you'll have C code in the brightscript interpreter finding the matching player for the update rather than having to walk an array and test the id for every entry.
  • Thanks!

    There are a couple of solid ideas here.

    Creating an roAssociativeArray object every loop through is just stupid and I'm sure it's eating a few milliseconds. I didn't even realize I was doing it, it is not necessary.

    The last suggestion is probably the best one, instead of having an array of associative arrays, I could have an associative array of associative arrays. Then I'm guessing I could just do a check like...


    id = params.id 'or something like this
    If this.players.id <> invalid
    'then do all of the movements for the player
    else
    'add the player to the array
    end if



    It would be a lot faster than looping through the array of players I'm sure, thanks a bunch! It does mean some changes to my code, but that's why I asked this question now before I got too far along 😄
  • Veeta you are my hero! I am now getting a maximum of 5ms for 50 active players!!! So much better, I used to crash the game if I got up to 30+ players, now my 8 core gaming computer is the bottleneck :shock: . (50 virtual game clients at once is about all it can do). Here is my new code if anyone is curious.

           
    While this.udp.isReadable()
    received = this.udp.receive(this.buffer, 0, 20)
    if received > 0
    params = {}
    params.id = resolve_two_byte_integer(this.buffer[12],this.buffer[13])
    id_string = params.id.tostr()
    params.x = resolve_two_byte_integer(this.buffer[14],this.buffer[15])
    params.y = resolve_two_byte_integer(this.buffer[16],this.buffer[17])
    params.color = this.buffer[18]
    params.destroy = this.buffer[19]
    id_exists = false
    player = this.players.Lookup(id_string)
    if player <> invalid
    this.players[id_string].x = params.x
    this.players[id_string].y = params.y
    id_exists = true
    if params.destroy = 1
    print "Removed player - id : " ; this.players[a].id
    this.players[id_string].sprite.Remove()
    this.players.Delete(id_string)
    end if
    end if
    if not id_exists and params.destroy = 0
    params.sprite = this.compositor.NewSprite(270, 500, this.region_ring[params.color])
    params.sprite.SetData(params.id)
    this.players.AddReplace(id_string, params)
    end if
    end if
    End While


    I didn't remove the params = {} object creation, but it really doesn't seem to have much of an effect.

    Thanks again! 😛