Jump to content

getElementsByType performance - more efficient way


Recommended Posts

Hello guys,

I have question how much efficient is to call 

for key, player in ipairs(getElementsByType("player")) do

in OnClientRender function? Is there any other more performance efficient way?

My another question is if getElementData in OnClientRender affects performance? 

Thanks a lot!

Link to comment
  • Moderators
1 hour ago, Killbean said:

in OnClientRender function?

The more entities it finds, the more performance it cost. (!!!especially if you loop over them)

 

 

1 hour ago, Killbean said:

Is there any other more performance efficient way?

 

1.

A way to improve performance could be done by only get the streamed in players.

getElementsByType("player", root, true)

For example if you are drawing name-tags on players, you want to draw them only on players close by. By pre narrowing down the segment of players, this will reduce the amount of loops you are going to preform.

 for key, player in ipairs(getElementsByType("player", root, true)) do 

 

2.

And switching to a more basic loop could also help a lot with the performance.

for i=1, #table do
  
end

 

3.

If the element type isn't a player, scoping the function to the resource which creates a specific element, could also help with performance.

getElementsByType("vehicle", resourceRoot, true)

 

 

 

 

  • Like 3
Link to comment
  • MTA Anti-Cheat Team

If you can avoid looping all elements of a certain type on the server up to 70 times per second (that's what render event is), you should do so by all means for performance reasons.

Using something like getElementsWithinRange or thinking of alternative solutions like putting the elements you need into a table for use (avoiding constant getting) is much better. I would also advise using that function before the solution of looping for streamedIn from the post above (for any scenario when it's like getting players nearby for rendering things like nametags), as it's even a little more optimized.

@Killbean

3 hours ago, Killbean said:

My another question is if getElementData in OnClientRender affects performance? 

The real culprit is setElementData, as long you keep the amount of getElementData's in render event below 4, you should be fine. The same applies to most other things you do in onClientRender: special care needs to be taken, try to keep the function as simple as possible and add as many checks and conditions as you can to stop costly unnecesary execution in an early stage.

Better yet, avoid the render event entirely when you can (it's performance killer number 1, at least in the hands of most scripters on MTA these days) and think of other ways like static drawing your images and other stuff, and getting data you need at a high interval (hence using render) with a short timer..

  • Like 1
Link to comment

@Dutchman101 already mentioned putting elements into a table, and I want to elaborate on that.

These functions that return the lists of elements, they create a new table and fill it with elements every time they're called, which is inefficient to do repeatedly if we can reuse previously attained information. An example:

local players = {}

local function resourceStarted()
    -- when the script starts, we populate the table with players that are already playing
    for key, player in ipairs(getElementsByType("player")) do
        players[player] = true
    end
end
addEventHandler("onClientResourceStart", resourceRoot, resourceStarted)

local function playerJoined()
    -- when a player joins, we add that player to the table
    players[source] = true
end
addEventHandler("onClientPlayerJoin", root, playerJoined)

local function playerQuit()
    -- when a player quits, we remove that player from the table
    players[source] = nil
end
addEventHandler("onClientPlayerQuit", root, playerQuit)

-- looping through all players:
for player in pairs(players) do

end

That is, we only retrieve the elements with getElementsByType at the beginning, and keep track of subsequent changes by ourselves. If you only want to track the streamed in elements, you can add the needed arguments to getElementsByType like @IIYAMA showed and replace "onClientPlayerJoin" and "onClientPlayerQuit" with "onClientElementStreamIn" and "onClientElementStreamOut" respectively. But then again, you will also need to use getElementType to filter out elements of other types.

Note that whereas getElementsByType returns a sequence (the key is a number, the value is an element), the table in my example is a set (the key is an element, the value is true). Looping is slightly different for that reason.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...