drevnii Posted August 1, 2020 Share Posted August 1, 2020 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 ds1-e Posted August 4, 2020 Scripting Moderators Share Posted August 4, 2020 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 2 Link to comment
Moderators IIYAMA Posted August 4, 2020 Moderators Share Posted August 4, 2020 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 Fast data rate / requires a slow interval Run code directly / (with elementdata that is only possible for the second time you set the data) More secure No auto download for new players Specify target players* *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 1 Link to comment
Scripting Moderators ds1-e Posted August 4, 2020 Scripting Moderators Share Posted August 4, 2020 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 1 Link to comment
drevnii Posted August 5, 2020 Author Share Posted August 5, 2020 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 ds1-e Posted August 5, 2020 Scripting Moderators Share Posted August 5, 2020 (edited) 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 August 5, 2020 by majqq 1 Link to comment
Moderators IIYAMA Posted August 5, 2020 Moderators Share Posted August 5, 2020 (edited) 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 August 5, 2020 by IIYAMA 2 Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now