Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Romans_I_XVI
Roku Guru

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!
0 Kudos
3 REPLIES 3
Veeta
Visitor

Re: Can you make this code more efficient?

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.
0 Kudos
Romans_I_XVI
Roku Guru

Re: Can you make this code more efficient?

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 😄
0 Kudos
Romans_I_XVI
Roku Guru

Re: Can you make this code more efficient?

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! 😛
0 Kudos