Technical Question - GetObjectByTag or...
#1
Posté 19 août 2011 - 05:10
The first script uses GetObjectByTag, where all the lamps (probably across the module) would have the same tag; the second uses GetObjectByType followed by GetLocalInt.
The dealbreaker here is which one would be most efficient/less strenuous on the resources? I've been told GetObjectByTag is pretty reliable but it depends on how the engine itself keeps track of what it's scanning for. If an area is large with many doors and placeables, and GetObjectByTag cycles all things considered an object (doors, placeables, creatures, etc) to compile a list of valid tags, it seems like it might end up slower.
Now this isn't a huge deal, but it's something that piqued my curiosity - both scripts run fine, but every bit of streamlining counts. Replies and/or debate is appreciated!
#2
Posté 19 août 2011 - 06:18
Where does the GetObjectByType function come from. NWNx? or an Include?
If it comes from NWNx it may be faster.
If it is from an include, it is a wrapper?? well I dont know. GetNeareast Object maybe?
I really thing nither one is the answer to your question. I would design a system where the objects(torches only had to be searcherd for once. That way it really would not matter how hard they where to find the first time, since it would only be done once.
you could either do what bioware did with waypoints, Serarching for them the first time and storing them in a list of local objects for future calls.
or
daisy chain them after finding them the first time. You could do that by storing a local object on the first one found that points to the second one. on the second one you would store a local object that points to the second one. ect.
#3
Posté 19 août 2011 - 09:27
While the Lexicon suggests it's PC/NPC, it doesn't state that it won't also retrieve objects. I suppose likely I can slap a script together to test it, but that might be a way to do it if it includes all objects, not just creatures.
Edit: Nope, looks like the faction setting is likely just for determining who'll respond to shouts from the placeables.
Modifié par Failed.Bard, 19 août 2011 - 09:35 .
#4
Posté 19 août 2011 - 09:11
Too bad about the faction script, though.
Modifié par Hardcore UFO, 19 août 2011 - 09:12 .
#5
Posté 19 août 2011 - 09:37
#6
Posté 19 août 2011 - 11:04
#7
Posté 20 août 2011 - 05:06
Funky
#8
Posté 20 août 2011 - 12:58
The module keep a sorted array of all tags, which is used by GetObjectByTag. So no matter the number of objects you have in your module, GetObjectByTag will be very fast.
GetNearestObjectByTag doesn't use this sorted array and prefer looping through all objects in the area and it also need to check the distance of each object found... if you have many objects in your area and fewer objects with the tag that you are looking for, you may even want to use this function to get the nearest object with a specific tag:
object MyGetNearestObjectByTag(string sTag, object oTarget=OBJECT_SELF)
{
int nNth = 0;
float fNearestDistance = 100000.0;
object oNearestObject;
object oTargetArea = GetArea(oTarget);
object oObject = GetObjectByTag(sTag, nNth);
while (oObject != OBJECT_INVALID)
{
if (GetArea(oObject) == oTargetArea)
{
float fDistance = GetDistanceBetween(oObject, oTargetArea);
if (fDistance < fNearestDistance)
{
fNearestDistance = fDistance;
oNearestObject = oObject;
}
}
oObject = GetObjectByTag(sTag, ++nNth);
}
return oNearestObject;
}
Modifié par Mavrixio, 20 août 2011 - 01:00 .
#9
Posté 20 août 2011 - 03:50
Interesting theory. In practice, however, completely wrong. I can't speak to the array, having not peeped that part of the engine, but GObT was incredibly slow in usage - one of several reasons we stopped using it. Granted, the distance-measuring in GNObT is wasteful in many cases, but it still FAR outperforms GObT in practice - probably because it's dealing with a few hundred objects instead of every object in the module. Have you done any actual profiling, or are you speaking solely from a theoretical perspective?Mavrixio wrote...
It is the opposite... you never want to you GetNearestObjectByTag, if you are concerned by efficiency.
The module keep a sorted array of all tags, which is used by GetObjectByTag. So no matter the number of objects you have in your module, GetObjectByTag will be very fast.
Funky
#10
Posté 20 août 2011 - 06:10
#11
Posté 20 août 2011 - 07:29
FunkySwerve wrote...
Interesting theory. In practice, however, completely wrong. I can't speak to the array, having not peeped that part of the engine, but GObT was incredibly slow in usage - one of several reasons we stopped using it. Granted, the distance-measuring in GNObT is wasteful in many cases, but it still FAR outperforms GObT in practice - probably because it's dealing with a few hundred objects instead of every object in the module. Have you done any actual profiling, or are you speaking solely from a theoretical perspective?Mavrixio wrote...
It is the opposite... you never want to you GetNearestObjectByTag, if you are concerned by efficiency.
The module keep a sorted array of all tags, which is used by GetObjectByTag. So no matter the number of objects you have in your module, GetObjectByTag will be very fast.
Funky
Yes, i have tested it.
It certainly depend on the number of object the number of object in the area, i dont have stat about that, but for if there's 100+ object int the area, then GetObjectByTag is 2-3 times faster than GetNearestObjectByTag, I dont know you, but personally we have areas with 1000+ placeables, so GetNearestObjectByTag is a no-no.
#12
Posté 20 août 2011 - 07:42
#13
Posté 21 août 2011 - 12:09
We found that GNoBT outperformed GObT radically even when our mod was much smaller - there was no evidence of any kind of optimization on GObT. It could take a second or two, even, which is outrageous as compared to GNObT.henesua wrote...
Funky, did you find at what point GNObT outperforms GObT? How many objects (roughly speaking) do you need to have for this to matter?
Mavrixio wrote...
Yes, i have tested it.
It certainly depend on the number of object the number of object in the area, i dont have stat about that, but for if there's 100+ object int the area, then GetObjectByTag is 2-3 times faster than GetNearestObjectByTag, I dont know you, but personally we have areas with 1000+ placeables, so GetNearestObjectByTag is a no-no.
You say you've tested it, but you don't have any statistics on performance by object count? How exactly did you test it? I'd be very interested to see your profiling on it.
Also, if you have areas with 1k+ placeables, I'm a lilttle less inclined to take your claims about performance seriously. That's an unbelievable number, even if you're really decking an area out. Have you actually counted, or are you guestimating? The most obscene placeable count on HG is in the 500s, where I went seriously overboard decking out the Forest of Poisoned Dreams in Shedaklah with extra mushrooms in order to get the right effect.
For both of you, here's our mod set out in placeable and tile count, for purposes of comparison:
HG placeable/tile counts
FWIW, we stopped using GObT when the mod was less than half its current size.
Funky
#14
Posté 21 août 2011 - 01:37
I dont have the formula on the top of my head, but the time that it takes to access an element in a sorted array can be considered as constant... so no matter the size of your module, GetObjectByTag will be relatively fast, it can easely be faster than GetLocalObject if you have many variables on the source.
Modifié par Mavrixio, 21 août 2011 - 01:37 .
#15
Posté 21 août 2011 - 01:56
That said... I certainly wasn't doubting you and pressing for your data. I just wanted to know what you thought on the matter.
Mavrixio, all I have to say is: show the data or it didn't happen.
#16
Posté 21 août 2011 - 02:04
Lol, I didn't think you were - I just like to put all the data I have on a topic out there. Knowing how many places are in your mod, or the average per area, or per tile, can come in handy.henesua wrote...
That said... I certainly wasn't doubting you and pressing for your data. I just wanted to know what you thought on the matter.
One reason that I'm highly skeptical of the 1k placeable per area claim is that even a couple hundred places in a small enough space can cause huge amounts of lag, as the server updates the description for the client every time they come into visual range. We actually had to move our Pillar of Skulls in Avernus for this reason - it's original position was too close to the Tiamat fight in the area, and players moving in and out of sight of it was generating immense amounts of lag.
Anyway, what he's saying runs counter to all my experience, but who knows, maybe they optimized GObT in one of the later updates. If he's not going to show any profiling, though, I have no reason to suspect that that's the case. As you say..show it or it didn't happen.
Funky
#17
Posté 21 août 2011 - 02:10
Faster than GetLocalObject? That's even harder to believe. By the way, someone did some profiling a while back that shows that variable read times don't noticeably increase until you hit around 5k variables on an object, so the claim that this is only the case 'if you have many variables on the source' smells a bit too - I've yet to see an application outside the PRC Character Creator that slammed even close to that many vars on an object - even counting things like dynamic convo pseudoarrays, which only hit a couple hundred vars.Mavrixio wrote...
I dont have the formula on the top of my head, but the time that it takes to access an element in a sorted array can be considered as constant... so no matter the size of your module, GetObjectByTag will be relatively fast, it can easely be faster than GetLocalObject if you have many variables on the source.
Do you have ANY profiling on GObT? You're making me very curious, if nothing else...
Funky
#18
Posté 21 août 2011 - 03:28
void TestLocalVars(int nCount)
{
object oTest = CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetStartingLocation());
int i;
for (i=0; i<nCount; i++) SetLocalObject(oTest, IntToString(i), oTest);
StartTimer();
for (i=0; i<10000; i++) GetLocalObject(oTest, "test");
SendMessageToPC(OBJECT_SELF, IntToString(nCount)+"vars: " + IntToString(EndTimer())+"ms");
DestroyObject(oTest);
}
//test of GetLocalObject
TestLocalVars(10);
TestLocalVars(20);
TestLocalVars(100);
TestLocalVars(200);
TestLocalVars(500);
TestLocalVars(1000);
TestLocalVars(2000);
//test of GetObjectByTag
StartTimer();
for (i=0; i<10000; i++) GetObjectByTag("theres no objects with this tag");
SendMessageToPC(oPC, "GetObjectByTag: " + IntToString(EndTimer())+"ms");
//test of GetNearestObjectByTag
StartTimer();
for (i=0; i<10000; i++) GetNearestObjectByTag("theres no objects with this tag");
SendMessageToPC(oPC, "GetNearestObjectByTag: " + IntToString(EndTimer())+"ms");
Output:
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 10vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 20vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 100vars: 100ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 200vars: 120ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 500vars: 200ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 1000vars: 300ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] 2000vars: 500ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] GetObjectByTag: 30ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:46] GetNearestObjectByTag: 590ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 10vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 20vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 100vars: 100ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 200vars: 110ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 500vars: 200ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 1000vars: 300ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 2000vars: 490ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] GetObjectByTag: 30ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] GetNearestObjectByTag: 580ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 10vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 20vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 100vars: 90ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:49] 200vars: 120ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 500vars: 200ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 1000vars: 290ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 2000vars: 480ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] GetObjectByTag: 30ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] GetNearestObjectByTag: 640ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 10vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 20vars: 80ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 100vars: 100ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 200vars: 120ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 500vars: 200ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 1000vars: 300ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] 2000vars: 500ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:52] GetObjectByTag: 30ms
[CHAT WINDOW TEXT] [Sat Aug 20 23:23:53] GetNearestObjectByTag: 690ms
#19
Posté 21 août 2011 - 05:24
Funky
Modifié par FunkySwerve, 21 août 2011 - 05:26 .
#20
Posté 21 août 2011 - 10:17
Modifié par GhostOfGod, 21 août 2011 - 10:18 .
#21
Posté 21 août 2011 - 10:37
The number of object in our module / the custom changes done to our nwserver, it wont reassure you
What there's to know is that:
GetObjectByTag > GetLocalObject
GetNearestObjectByTag is not in the competition, you it only when you have no choice.
GetLocalObject get slightly slower with the number of variable on the object, but at a proportional speed... the performace of it could be calculated by (x + y * z) where x is the constant speed (slower that GetObjectByTag by itself, if you have a large module), y is the number of variables and z is performance decrease per variable (very small but after 300-500 variables you already doubled the default speed)
Modifié par Mavrixio, 21 août 2011 - 01:48 .
#22
Posté 21 août 2011 - 11:50
I'm not sure my complete mod placeable count, likely 1500-2000 though, since it's 50 areas.
500 iterations of each search, in an attempt to get the run time high enough to compare.
Script one, labeled unimaginatively "test_1"
void main()
{
object oTest;
int i;
for (i = 1; i <= 500; i ++)
{
oTest = GetObjectByTag ("TEST_FIND_ME");
}
SpeakString ("Done");
}
Script Two, "test_2"
void main()
{
object oTest;
int i;
for (i = 1; i <= 500; i ++)
{
oTest = GetNearestObjectByTag ("TEST_FIND_ME");
}
SpeakString ("Done");
}
Run times:
test_1 0 msec 1 calls
test_2 38 msec 1 calls
I'll try it again with only 50 placeables between, to see how much of a speed difference it makes per placeable it has to check, but I expect it has to check every single placeable in the area, then compare tags and distances, so it'll still be substantially slower.
Edit: 50 between, 83 placeables total in area:
test_1 0 msec 1 calls
test_2 25 msec 1 calls
test_1 20 msec 10 calls
test_2 241 msec 10 calls
Modifié par Failed.Bard, 21 août 2011 - 12:01 .
#23
Posté 21 août 2011 - 01:32
#24
Posté 21 août 2011 - 02:36
Mavrixio wrote...
StartTimer and EndTimer are custom nwnx functions like nwnx_timer on Windows.
The number of object in our module / the custom changes done to our nwserver, it wont reassure you
What there's to know is that:
GetObjectByTag > GetLocalObject
GetNearestObjectByTag is not in the competition, you it only when you have no choice.
GetLocalObject get slightly slower with the number of variable on the object, but at a proportional speed... the performace of it could be calculated by (x + y * z) where x is the constant speed (slower that GetObjectByTag by itself, if you have a large module), y is the number of variables and z is performance decrease per variable (very small but after 300-500 variables you already doubled the default speed)
I already know what you're claiming. I'm asking for data to help in verifying those claims. Again:
And what size is the module? Object count? Objects in area? The amount
of information you're leaving out isn't helping. Also, if you provide
the full function and includes, I can run it on HG for comparison.
Funky
#25
Posté 21 août 2011 - 02:41
It's not just placeables, remember, but all objects. Places are typically the most numerous types, but there's still other heavy hitters, like items, and triggers, along with creatures, doors, waypoints, etc.Failed.Bard wrote...
I was curious about this myself, so I set up a test for it in my little mod using OnCick on placeables to trigger the scripts. 133 placeables in the area, exactly 100 barrell placeables placed between script trigger placeable and the placeable it was looking for, to simulate a somewhat crowded are.
I'm not sure my complete mod placeable count, likely 1500-2000 though, since it's 50 areas.
Funky





Retour en haut






