Jump to content

[HELP] Event vs ElementData


drevnii

Recommended Posts

Hi, for example

Exist N player, each of them contains: 

(ElementData version) 1 ElementData with status table(hunger, thirst, etc.)

(Event version) Every second, the player's client receives information from the server with status table

Which of these methods gives more performance? (server and client)

Link to comment
  • Scripting Moderators
On 01/08/2020 at 17:49, drevnii said:

Hi, for example

Exist N player, each of them contains: 

(ElementData version) 1 ElementData with status table(hunger, thirst, etc.)

(Event version) Every second, the player's client receives information from the server with status table

Which of these methods gives more performance? (server and client)

If you could go with tables, then do it. From my own experience, i'd say that tables are way more efficient rather than element data. However you should remember about few things, when it comes to passing data (doesn't matter if it's element data or tables).

1) How often data is passed - the less - the better (use timers for reduction, aka buffers; collect pack of data, and then send it after 100-200 ms).

2) How much data do you pass - if you do not need to pass whole data, then don't do it (unless on init). Send certain values.

3) How you pass data - it should be well maintained to avoid issues. With tables it's easier to do. Haven't using using element data for a long time, but i'm pretty sure that:

setElementData(client, "data", true) -- equals to 1 triggerClientEvent

So every call of element data is one trigger, which is pretty bad. Imagine that you need to set 30 data at once (feels bad). You can see that tables won here :)

local dataTable = {}
local playerElement = getPlayerFromName("SERIOUSLY?")

dataTable[playerElement] = {}
dataTable[playerElement][1] = "First index."
dataTable[playerElement][2] = "Second index."

triggerClientEvent(root, "onClientDataSync", resourceRoot, dataTable) -- 1 call

setElementData(playerElement, "First index", true) -- 1 call
setElementData(playerElement, "Second index", true) -- 2 call

-- Element data will trigger separately for each call.

4) Don't do those:

local players = getElementsByType("player")
local playerElement = false

for i = 1, #players do
	playerElement = players[i]
	triggerClientEvent(playerElement, "onClientEvent", playerElement)
end

This will cause that triggerClientEvent will be called * count of players.

Instead do:

local players = getElementsByType("player")

triggerClientEvent(players, "onClientEvent", resourceRoot)

Since triggerClientEvent accepts table of players. And it would be just one call.

Extra code to test by @IIYAMA.

local sendingDelay = 100 -- ms
local fps = 60

local timeSlice = 1000/fps
local dataReduction = sendingDelay/timeSlice
print("~"..(dataReduction - 1 ).." x times LESS per "..sendingDelay.."ms")

You can see how certain delays affect server when passing data.

If you have any other questions, feel free to ask.

PS: Recently element data got some update with subscription mode, but i still advice to go for tables if you can :)

  • Like 2
Link to comment
  • Moderators
37 minutes ago, majqq said:

setElementData(client, "data", true) -- equals to 1 triggerClientEvent

@majqq

Keep in mind that even if there is no data added, the triggerClientEvent it's (5x?) packet size is bigger than that from setElementData. And triggerClientEvent is also a lot faster and therefore it's data rate is higher, if no buffer is used, it will cause blocking the network a lot faster than with setElementData.

So if you broadcast to all players, triggerClientEvent might not always be the best option, because you do not reduce data.

triggerClientEvent

*Before the beta from below.


 

There is a new function available in the beta for element data, that will help shrink the data usage of players that do not need the data.

https://wiki.multitheftauto.com/wiki/AddElementDataSubscriber

More information here:

https://wiki.multitheftauto.com/wiki/SetElementData

 

 

 

 

 

  • Like 1
Link to comment
  • Scripting Moderators
19 minutes ago, IIYAMA said:

@majqq

Keep in mind that even if there is no data added, the triggerClientEvent it's (5x?) packet size is bigger than that from setElementData. And triggerClientEvent is also a lot faster and therefore it's data rate is higher, if no buffer is used, it will cause blocking the network a lot faster than with setElementData.

So if you broadcast to all players, triggerClientEvent might not always be the best option, because you do not reduce data.

Thank you for clarifying ?

  • Like 1
Link to comment

Thx guys!

23 hours ago, majqq said:

1) How often data is passed - the less - the better (use timers for reduction, aka buffers; collect pack of data, and then send it after 100-200 ms).

For unknown reason I didn't even think this way, thanks for the reminder.

23 hours ago, majqq said:

2) How much data do you pass - if you do not need to pass whole data, then don't do it (unless on init). Send certain values.

So, (ElementData variant) if I send one value (food, thirst, etc.) instead of send a table with this values, is this faster? I ran a test and on average the tables were transferred faster than all the values one by one (Now I think that this is my mistake, because changing one value instead of a table should be faster.)

22 hours ago, IIYAMA said:

Keep in mind that even if there is no data added, the triggerClientEvent it's (5x?) packet size is bigger than that from setElementData.

Then I only need to send the date when it changes? 

In my mode, I keep a modular concept, if I need to transfer information from one resource to the server of two different resources, how can I do this?

Sorry for bad english XD

Link to comment
  • Scripting Moderators
40 minutes ago, drevnii said:

For unknown reason I didn't even think this way, thanks for the reminder.

I've found example of IIYAMA which should explain buffer (he taught me that! :D)

For element data it might look different. At the moment i can think of disabling sync (4th argument). And with help of tables do the rest.

Do not treat this code as a full solution, but more like a example.

-- Client

function onClientReceiveData(pData)
	local cachedData = false

	for i = 1, #pData do
		cachedData = pData[i]

		setElementData(cachedData[1], cachedData[2], cachedData[3], false)
	end
end
addEvent("onClientReceiveData", true)
addEventHandler("onClientReceiveData", root, onClientReceiveData)

function onClientDataSync(pData)
	--
end
addEvent("onClientDataSync", true)
addEventHandler("onClientDataSync", localPlayer, onClientDataSync)

-- Server

local buffersTable = {}

function setElementDataWithBuffer(pElement, pKey, pValue, pTimeout)
	if not buffersTable[pElement] then
		buffersTable[pElement] = setTimer(function(pElement)
			if isElement(pElement) then
				triggerClientEvent(root, "onClientReceiveData", pElement, buffersTable[pElement])
			end
			buffersTable[pElement] = nil
		end, pTimeout, 1, pElement)
	end

	return setElementData(pElement, pKey, pValue, false)
end

function onPlayerLogin()
	--triggerClientEvent(source, "onClientDataSync", source, buffersTable)
end
addEventHandler("onPlayerLogin", root, onPlayerLogin)

In order to make it work, you would need to track all changes applied with custom element data implementation (since it do not sync). While on tables it would be way easier to do.

Perhaps, there's other way but i don't think so.

40 minutes ago, drevnii said:

Then I only need to send the date when it changes? 

There's no reason to update data continuously, rather than on change.

40 minutes ago, drevnii said:

In my mode, I keep a modular concept, if I need to transfer information from one resource to the server of two different resources, how can I do this?

Maybe with help of events.

You can use trigger to have a communication between two resources (not sure if event with same name on two different resources it's possible, but should be).

local importedCache = exports.cache:getClientFiles() -- getting client files (they are loaded in different resource)

-- Iterating over table, saving some data...

triggerEvent("onClientCacheLoaded", localPlayer) -- I couldn't get any other solution. Since exports take some time, and due of different script order, i am triggering event which exist on same side (it could be different side though). To let know that files are ready to use. It would work even if event is registered later than script which catch loaded files.

 

Edited by majqq
  • Like 1
Link to comment
  • Moderators
1 hour ago, drevnii said:

Then I only need to send the date when it changes? 

That is the first step. Depending on the dimension size. Like milliseconds/seconds/minutes/hours/days, you can also save a lot of data at these 2 dimensions: milliseconds/seconds

Are those dimensions included? If yes, then I can explain a little bit more.

 

1 hour ago, drevnii said:

In my mode, I keep a modular concept, if I need to transfer information from one resource to the server of two different resources, how can I do this?

Server

triggerClientEvent(receivers, "<eventName>", resourceRoot, date)

Client

-- <triggerClientEvent resource>
addEvent("<eventName>", true) 
-- <resource 1>
addEventHandler("<eventName>", root, function () 
  
end)


-- <resource 2>
addEventHandler("<eventName>", root, function () 
  
end)


----------------------
-- or more specified.
----------------------


-- <resource 1>

addEventHandler("<eventName>", getResourceRootElement ( getResourceFromName ("<triggerClientEvent resource name>")), 
function () 
  
end, false)


-- <resource 2>
addEventHandler("<eventName>", getResourceRootElement ( getResourceFromName ("<triggerClientEvent resource name>")), 
function () 
  
end, false)

 

 

 

Edited by IIYAMA
  • Like 2
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...