Scripting Moderators ds1-e Posted May 12, 2019 Scripting Moderators Share Posted May 12, 2019 Hey. I would like to integrate bone attach with my gamemode, and also improve code a bit. First of all, question about meta of bone attach. <script src="bone_attach.lua" /> <script src="bone_attach_c.lua" type="client" cache="false" /> <script src="attach_func.lua" /> <script src="attach_func.lua" type="client" cache="false" /> <script src="bone_pos_rot.lua" type="client" cache="false" /> If script doesn't have defined type, then by default it's server/shared? So i thought about those ways. 1. Use more locals - following this performance tips? 2. Replace onClientRender to render events by IIYAMA - probably this should help a little bit though. 3. Any other way which i don't know about? Link to comment
Moderators IIYAMA Posted May 12, 2019 Moderators Share Posted May 12, 2019 8 hours ago, majqq said: If script doesn't have defined type, then by default it's server/shared? server by default. 8 hours ago, majqq said: 3. Any other way which i don't know about? A critical one: Loop over an array table structure. Not an object table structure. But that doesn't mean you can't use both. local boneAttachments_array = {} local boneAttachments_object = {} local newAttachment = { posX, posY, ped -- etc. } boneAttachments_array[#boneAttachments_array + 1] = newAttachment boneAttachments_object[ped] = newAttachment Access the (same) data: for i=1, #boneAttachments_array do local boneAttachment = boneAttachments_array[i] end local boneAttachment = boneAttachments_object[ped] 1 Link to comment
Scripting Moderators ds1-e Posted May 12, 2019 Author Scripting Moderators Share Posted May 12, 2019 6 hours ago, IIYAMA said: server by default. A critical one: Loop over an array table structure. Not an object table structure. But that doesn't mean you can't use both. local boneAttachments_array = {} local boneAttachments_object = {} local newAttachment = { posX, posY, ped -- etc. } boneAttachments_array[#boneAttachments_array + 1] = newAttachment boneAttachments_object[ped] = newAttachment Access the (same) data: for i=1, #boneAttachments_array do local boneAttachment = boneAttachments_array[i] end local boneAttachment = boneAttachments_object[ped] Where exactly i should use int loop, or we're about changing it in this function? function forgetNonExistingPeds() local checkedcount = 0 while true do for element,ped in pairs(attached_ped) do if not isElement(ped) then clearAttachmentData(element) end checkedcount = checkedcount+1 if checkedcount >= 1000 then coroutine.yield() checkedcount = 0 end end coroutine.yield() end end Link to comment
Moderators IIYAMA Posted May 12, 2019 Moderators Share Posted May 12, 2019 1 hour ago, majqq said: Where exactly i should use int loop, or we're about changing it in this function? function forgetNonExistingPeds() local checkedcount = 0 while true do for element,ped in pairs(attached_ped) do if not isElement(ped) then clearAttachmentData(element) end checkedcount = checkedcount+1 if checkedcount >= 1000 then coroutine.yield() checkedcount = 0 end end coroutine.yield() end end At places with this kind of loops: for element,ped in pairs(attached_ped) do If you want to optimise this, it will take at least an hour to implement the new table structure. Ask yourself the question: "Do you want to spend your time on that?" Also the code from your previous reply could be merged with: Spoiler function putAttachedElementsOnBones() for element,ped in pairs(attached_ped) do if not isElement(element) then clearAttachmentData(element) elseif isElementStreamedIn(ped) then local bone = attached_bone[element] local x,y,z = getPedBonePosition(ped,bone_0[bone]) local xx,xy,xz,yx,yy,yz,zx,zy,zz = getBoneMatrix(ped,bone) local offx,offy,offz = attached_x[element],attached_y[element],attached_z[element] local offrx,offry,offrz = attached_rx[element],attached_ry[element],attached_rz[element] local objx = x+offx*xx+offy*yx+offz*zx local objy = y+offx*xy+offy*yy+offz*zy local objz = z+offx*xz+offy*yz+offz*zz local rxx,rxy,rxz,ryx,ryy,ryz,rzx,rzy,rzz = getMatrixFromEulerAngles(offrx,offry,offrz) local txx = rxx*xx+rxy*yx+rxz*zx local txy = rxx*xy+rxy*yy+rxz*zy local txz = rxx*xz+rxy*yz+rxz*zz local tyx = ryx*xx+ryy*yx+ryz*zx local tyy = ryx*xy+ryy*yy+ryz*zy local tyz = ryx*xz+ryy*yz+ryz*zz local tzx = rzx*xx+rzy*yx+rzz*zx local tzy = rzx*xy+rzy*yy+rzz*zy local tzz = rzx*xz+rzy*yz+rzz*zz offrx,offry,offrz = getEulerAnglesFromMatrix(txx,txy,txz,tyx,tyy,tyz,tzx,tzy,tzz) if (string.find(objx..objy..objz, "a")) then setElementPosition(element, x, y, z) else setElementPosition(element, objx, objy, objz) end if (not string.find(offrx..offry..offrz, "a")) then setElementRotation(element, offrx, offry, offrz, "ZXY") else setElementPosition(element,getElementPosition(ped)) end end end end addEventHandler("onClientPreRender",root,putAttachedElementsOnBones) 1 Link to comment
Scripting Moderators ds1-e Posted May 12, 2019 Author Scripting Moderators Share Posted May 12, 2019 1 hour ago, IIYAMA said: At places with this kind of loops: for element,ped in pairs(attached_ped) do If you want to optimise this, it will take at least an hour to implement the new table structure. Ask yourself the question: "Do you want to spend your time on that?" Also the code from your previous reply could be merged with: Hide contents function putAttachedElementsOnBones() for element,ped in pairs(attached_ped) do if not isElement(element) then clearAttachmentData(element) elseif isElementStreamedIn(ped) then local bone = attached_bone[element] local x,y,z = getPedBonePosition(ped,bone_0[bone]) local xx,xy,xz,yx,yy,yz,zx,zy,zz = getBoneMatrix(ped,bone) local offx,offy,offz = attached_x[element],attached_y[element],attached_z[element] local offrx,offry,offrz = attached_rx[element],attached_ry[element],attached_rz[element] local objx = x+offx*xx+offy*yx+offz*zx local objy = y+offx*xy+offy*yy+offz*zy local objz = z+offx*xz+offy*yz+offz*zz local rxx,rxy,rxz,ryx,ryy,ryz,rzx,rzy,rzz = getMatrixFromEulerAngles(offrx,offry,offrz) local txx = rxx*xx+rxy*yx+rxz*zx local txy = rxx*xy+rxy*yy+rxz*zy local txz = rxx*xz+rxy*yz+rxz*zz local tyx = ryx*xx+ryy*yx+ryz*zx local tyy = ryx*xy+ryy*yy+ryz*zy local tyz = ryx*xz+ryy*yz+ryz*zz local tzx = rzx*xx+rzy*yx+rzz*zx local tzy = rzx*xy+rzy*yy+rzz*zy local tzz = rzx*xz+rzy*yz+rzz*zz offrx,offry,offrz = getEulerAnglesFromMatrix(txx,txy,txz,tyx,tyy,tyz,tzx,tzy,tzz) if (string.find(objx..objy..objz, "a")) then setElementPosition(element, x, y, z) else setElementPosition(element, objx, objy, objz) end if (not string.find(offrx..offry..offrz, "a")) then setElementRotation(element, offrx, offry, offrz, "ZXY") else setElementPosition(element,getElementPosition(ped)) end end end end addEventHandler("onClientPreRender",root,putAttachedElementsOnBones) I would try, i'm sure by following your advice i could do that I just need a point to start off, and some more time (besides that, i'm doing a lot of other things, i'm asking about that, because i will need it in nearest future.) Link to comment
Scripting Moderators ds1-e Posted August 18, 2019 Author Scripting Moderators Share Posted August 18, 2019 Hey @IIYAMA Each day, with small steps am getting closer to that. But before i am going to start optimizing bone_attach, i want to be sure that i've optimized my other scripts correctly. This refers to Lua functions and MTA functions which are in _G table? So for example math. functions, tostring, tonumber, and shared functions which are available in client and server side aswell (getElementsByType, getElementPosition) ? I'm just asking because after testing localized things it gives me a different result (less or more ticks) Link to comment
Moderators IIYAMA Posted August 18, 2019 Moderators Share Posted August 18, 2019 28 minutes ago, majqq said: This refers to Lua functions and MTA functions which are in _G table? The _G table keeps track of all global variables. Not just functions and not all functions, as some can be saved in local variables. https://www.Lua.org/pil/14.html 31 minutes ago, majqq said: So for example math. functions, tostring, tonumber, and shared functions which are available in client and server side aswell (getElementsByType, getElementPosition) ? Yes, they are `shared` or rather copied. I honestly only localize my own functions. The last time I checked, I didn't notice any optimization by localize MTA functions. Every file has it's own scope, so making use of that is not a bad thing. My main reason for localization: You can use it to distinguish functions used within the file, from functions that are called from other files. The only thing I do with some Lua functions is this: local mathRandom = math.random 1 Link to comment
Scripting Moderators ds1-e Posted August 19, 2019 Author Scripting Moderators Share Posted August 19, 2019 5 hours ago, IIYAMA said: The _G table keeps track of all global variables. Not just functions and not all functions, as some can be saved in local variables. https://www.Lua.org/pil/14.html Yes, they are `shared` or rather copied. I honestly only localize my own functions. The last time I checked, I didn't notice any optimization by localize MTA functions. Every file has it's own scope, so making use of that is not a bad thing. My main reason for localization: You can use it to distinguish functions used within the file, from functions that are called from other files. The only thing I do with some Lua functions is this: local mathRandom = math.random Hi, thanks for answer. I've checked by myself and probably it worked for Lua functions (looks like), but for some reason on MTA functions it showed mostly less or rarely - more ticks, there was a few times when it taked even more than non-localized things. (maybe fault of fast restart of script but i don't think so). 1 Link to comment
Moderators IIYAMA Posted August 19, 2019 Moderators Share Posted August 19, 2019 11 hours ago, majqq said: but for some reason on MTA functions it showed mostly less or rarely - more ticks, there was a few times when it taked even more than non-localized things. I had the same results, so nothing has changed. It might even be possible that they are already localized in some unknown way. Just as the predefined source variable is localized when an event has been triggered. 1 Link to comment
Scripting Moderators ds1-e Posted September 2, 2019 Author Scripting Moderators Share Posted September 2, 2019 (edited) On 19/08/2019 at 17:28, IIYAMA said: I had the same results, so nothing has changed. It might even be possible that they are already localized in some unknown way. Just as the predefined source variable is localized when an event has been triggered. Hey @IIYAMA Probably i've finished this. I just need to fix rotation, and test server-side. But at the moment, i've tested it only by myself, with 1 attached object. This is the result: - Localized Lua functions, tables, and any other functions which returns data. - Used int loop instead of pairs, didn't took me so long since i'm practising tables from the time when you showed me how to sync data between server/client. - With thing above i get rid of timer, coroutine and while loop. (hopefully this will fix an annoying error, i check if element actually exists, if not, script removing it from table) Glad that you helped me Edited September 2, 2019 by majqq Link to comment
Moderators IIYAMA Posted September 2, 2019 Moderators Share Posted September 2, 2019 2 hours ago, majqq said: This is the result: And what was it before? If you want to measure this correctly you need multiple samples. 0 AttachElements (idle). 10 AttachElements (doing something). 1000 AttachElements (doing a lot). 10000 AttachElements (doing too much). Link to comment
Scripting Moderators ds1-e Posted September 2, 2019 Author Scripting Moderators Share Posted September 2, 2019 2 hours ago, IIYAMA said: And what was it before? If you want to measure this correctly you need multiple samples. 0 AttachElements (idle). 10 AttachElements (doing something). 1000 AttachElements (doing a lot). 10000 AttachElements (doing too much). Sorry but i didn't last 60 seconds at last test, at 1000 objects Screenshot comparing old one and new one, running at same time. 1 object: 10 objects: 100 objects: 1000 objects: 1 Link to comment
Moderators IIYAMA Posted September 2, 2019 Moderators Share Posted September 2, 2019 1 hour ago, majqq said: Screenshot comparing old one and new one, running at same time. More than 50% performance boost. Nicely done! 1 Link to comment
Einheit-101 Posted September 9, 2019 Share Posted September 9, 2019 (edited) So you say its always a bad idea to access a table with an element as index? table[vehicle] is worse than table[number] ? Is there any reasonable explanation why that is the case or is it just a funfact? Edited September 9, 2019 by Einheit-101 Link to comment
Moderators IIYAMA Posted September 9, 2019 Moderators Share Posted September 9, 2019 (edited) @Einheit-101 If we keep looping out of it and only talk about indexing. This below is just an assumption: If this is the userdata key: (which is at the very end just a complex and unique identifier.) "userdata-324ftfdbgfd" And this is the data: table = { ["userdata-424ftfsdgsf"] = true, ["userdata-3sd3524ftfd"] = true, ["userdata-325524ftfdb"] = true, ["userdata-324ftfdbgfd"] = true } Depending on which algorithm is used, the search time variates. (algorithm < which I have no knowledge of) But if I would program this search, I might do it like this in my first try: I know already the type, so my start would be: "userdata-" >>> userdata-424ftfsdgsfuserdata-3sd3524ftfduserdata-325524ftfdbuserdata-324ftfdbgfd Collect all items with userdata. steps * items >>> userdata-424ftfsdgsfuserdata-3sd3524ftfduserdata-325524ftfdbuserdata-324ftfdbgfd print(string.byte("3")) -- 51 + update position * 4 + 4 steps >>> userdata-3sd3524ftfduserdata-325524ftfdbuserdata-324ftfdbgfd print(string.byte("s")) -- 115 print(string.byte("2")) -- 50 + update position * 3 + 3 steps >>> print(string.byte("4")) -- 52 userdata-325524ftfdbuserdata-324ftfdbgfd < found item in table + update position * 2 + 2 steps Lua would probably be better in this then I do. But this has multiple search steps in it, no matter what kind of algorithm you use. table = { true, -- 1 true, -- 2 true, -- 3 true -- 4 } table = { [1] = true, [2] = true, [3] = true, [4] = true } Finding the index in this kind of table should be technically be faster based on two ways. Position of the characters do not matter. It is a single value, the cpu knows very well how to work with that. As with user-data's/strings, not only the position matters, the value is also different: print(string.byte("a")) -- 97 Much complexer values X position. Everything is already placed in order if you keep the table as an clean array. Just as with cleaning your room. After the cleaning, you do not have to look everywhere in your room. You more or less know where to find what and how many things you have of it. Searching for item 4? no, no, no, yes (4 steps) Note: looping to find an item VS using a custom key to find an item is a different subject. If somebody knows how this really works, then that would be nice fun facts. Edited September 9, 2019 by IIYAMA 2 Link to comment
MayQuick Posted September 9, 2019 Share Posted September 9, 2019 So will you share with us your update?) P.S. Thx for the link to Lua performance. Very Useful :) Link to comment
Einheit-101 Posted September 10, 2019 Share Posted September 10, 2019 So the central message of you is that a table is being looked up faster when the key is shorter, which makes sense. 1 Link to comment
iDannz [Breno] Posted February 26, 2020 Share Posted February 26, 2020 maybe isElementOnScreen can help in pre render event Link to comment
Scripting Moderators ds1-e Posted February 27, 2020 Author Scripting Moderators Share Posted February 27, 2020 (edited) 12 hours ago, iDannz [Breno] said: maybe isElementOnScreen can help in pre render event Thanks for suggestion, but i already tested isElementOnScreen, it would cause object stay for a moment when not looking on it. However this was so far ago, so i might did something incorrect. Whatsoever performance in render can be improved by declaring variables out of rendering scope (so basically in main one), and reusing them. I will rewrite bone attach once again to apply some tricks what i've learnt since this topic (to gain even more than 50% performance boost), and let you know about results in this topic Edited February 27, 2020 by majqq Link to comment
iDannz [Breno] Posted February 27, 2020 Share Posted February 27, 2020 (edited) 31 minutes ago, majqq said: Thanks for suggestion, but i already tested isElementOnScreen, it would cause object stay for a moment when not looking on it. However this was so far ago, so i might did something incorrect. Whatsoever performance in render can be improved by declaring variables out of rendering scope (so basically in main one), and reusing them. I will rewrite bone attach once again to apply some tricks what i've learnt since this topic (to gain even more than 50% performance boost), and let you know about results in this topic I also got good results, this is the performance I got with 100 objects: 100 objects (looking directly at them): 100 objects (without looking at them): (I didn't notice any apparent problems when using isElementOnScreen, maybe I'll be back to test it soon) I would like to thank you and everyone who commented here, as this topic inspired me to learn a little more about optimization in Lua :D Edited February 27, 2020 by iDannz [Breno] 1 Link to comment
XaskeL Posted February 27, 2020 Share Posted February 27, 2020 I caught trend and I'm working on optimize bone_attach. 1000 objects in stream: 1 Link to comment
Moderators Patrick Posted February 27, 2020 Moderators Share Posted February 27, 2020 30 minutes ago, XaskeL said: I caught trend and I'm working on optimize bone_attach. And what did you say? Do you want to share it with me? And I don't have to do it too? Link to comment
XaskeL Posted February 27, 2020 Share Posted February 27, 2020 38 minutes ago, Patrick said: And what did you say? Do you want to share it with me? And I don't have to do it too? I want put out it on github. If you add server events and some functions for exports, then we can give people a good enough bone_attach Link to comment
Moderators Patrick Posted February 28, 2020 Moderators Share Posted February 28, 2020 2 hours ago, XaskeL said: I want put out it on github. If you add server events and some functions for exports, then we can give people a good enough bone_attach I'm in. Link to comment
Scripting Moderators ds1-e Posted April 25, 2020 Author Scripting Moderators Share Posted April 25, 2020 Hi. So after all i've decided to play with bone attach once again, had to fix CJ skin bug, and decided to squeeze out even more performance CPU: i5-9400F 1 attached object: 100 attached objects: 1 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