Which is fast? GetAllActorsOfClass vs GetAllActorsOfTag

This question is more of curiosity than something I need to know now.

I was wondering which will be faster between GetAllActorsOfClass or GetAllActorsWithTag.

I know that GetAllActorsOfClass will have to use the RTTI to determine weather actors is subclass of the passed class, and RTTI is always costly. Does UE4 has some internal optimization (like using tree to store RTTI data) which makes it faster?

And in GetAllActorsWithTag, UE4 definitely has to loop through all actors in scene and check if they have tag individually which means the more actors in scene the worst performance. But then again UE4 might have some optimizations for this too.

These are my assumptions. If anyone know what kind of optimization UE4 uses or which is faster to use please comment.

Thanks.

UE4 don’t use RTTI but it’s own reflection system. Each class have identificator UClass and each UObject instance has UClass* to identify it, compireing individual class is as fast as compering integers (class pointers which are memory addresses which compiler treats as integers with math/logic operators) and checking base depends on how much deep you search, loop will stop once it reach class you searching, you can check IsA function code youself:

I don’t think compiring 2-4 pointers will have much impact performance and it faster then compering strings of tags

But you need to note that function like GetAllActorsOfClass, GetAllActorsOfTag was made primerly for blueprint use, as blueprint don’t support iterators. UE4 got special iterators for vvariuous things including actor searching TActorIterator which you can use yourself to optimize things even more (for example stop iteriting if you found what you searching for). Function you trying to analize also using that iterator and puts everything in to array, but with iterator alone you can do things to actor imiditly if you want as they are found, once you know you did what you want you break a loop with break;

UClass* ActorClass = USomethingSomething::StaticClass();

for(TActorIterator<AActor> It((), ActorClass); It; ++It)
{
		AActor* Actor = *It;
        Actor->DoSomething();
}

Or with auto casting

for(TActorIterator<USomethingSomething> It(()); It; ++It)
{
		USomethingSomethingr* Actor = *It;
        Actor->DoSomething();
}

Case above only involves objects and classes in reflection system, all reflected objects has UField-based object created to identification and types of variables keeped in property level in property data inside either UClass or UStruct objects which are generated anyway whatever you like it ot not when you start up the engine, whole engine code depends on it so it impossible to get rid off. So you accessing that data only if you want, and even so it’s not that performance heavy as in most cases you just compering identificator of one object is with another identificator, which is pointer to pointer compare which as fast as integer. You can see all identification classes here:

TProperty | Unreal Engine Documentation <-those are UField too

When you place UCLASS(), UPROPERTY() etc in header file, the UnrealHeaderTool (UHT) parse those macros (those are dummy macros just for UHT, compiler ignores them… rether pastes empty text) and generate code to refister all of those object in reflection system which will create all those UClass, UProperty, UEmum object in memory when you start up the engine. All UObjects classes need to be reflected as, as object management system depends on it, otherwise it won’t see them at all, probably would crash either way if you would try to create such object.

3 Likes

Source looks pretty much the same to me (at a rough viewing) I also noticed it has a Cycle Counter in both Functions so it should show up in your Profiler in the GamePlayStatics group. Easiest way is probably to spawn a Bunch of random Actors with a Bunch of random Tags and see what runs faster. I assume you are able to make such a simple casetest on your own right?

Thanks thats a very detailed answer. Exactly what I was looking for. When I said RTTI, I wanted to mean reflection. I know C++ doesn’t have RTTI, we are asked to create a crude RTTI implementation as one of our assignments from which i gathered that its costly. Its totally different from how UE4 implements reflection. Yes string comparison is always costlier than integer comparison.
I didnt know about TActorIterator. this is amazing. Thanks again. :slight_smile:

I thought by RTTI you mean C++ standard RTTI with typeid and type_info etc ;p