Is casting expensive?

Was wondering if casting is more expensive performance wise than using interfaces?

I have heard people say casting is slow, but not in reference to interfaces. I don’t think it matters unless you are casting many times a second(tick) or something though.

I don’t know about the cost. But I wouldn’t worry about it too much. The benefit of polymorphism outweighs the performance cost of such things I’d argue.

This would be relevant if you’re running Blueprint in a tight loop and casting every iteration on a performance critical section. In which case I would argue that C++ is better option.

Based on my experience, I would not expect casting to be particularly slow compared to any other operation done in blueprints.
If you’re doing hard-core parallel data processing in C++, then yes, avoid dynamic casting in the inner loop. But that’s not something you do in blueprints :slight_smile:

I was curious about this too, so I went ahead and did some actual tests to find out. The results were that the difference is minimal, but that casting is in fact slightly faster than interfaces. In a real-world scenario however, there is no reason to worry about it, and it’s probably safe to say that this is at the very bottom of the list of things to consider for optimization. One might argue it’s not even on that list at all.

DATA

On an empty scene playing in the editor, eyeballing the FPS stats read-out, it looks like this:

Running 10 000 casts + function calls per frame takes 79 - 85 milliseconds/frame
Running 10 000 interface calls per frame takes 81 - 89 milliseconds/frame

So, there’s some overlap in those time intervals, but on average the cast approach is marginally faster. This test was run on a laptop with a 460M and 6 GB of RAM, so the absolute numbers are not interesting here, only the relative difference. There’s also the rendering overhead to take into account, which on this system was around 20 ms.

TEST SETUP

The level blueprint uses OnTick to run a for-loop that either calls an interface function, or performs a cast followed by a function call. The execution wire is moved manually to one or the other cases between tests:

The functions do something, but as little as possible:

57240c0fad08c4d6da324791c865378c8334a948.png

If you want to try it out yourself, the project can be downloaded here: https://dl.dropboxusercontent.com/u/2888286/CastVSInterface.zip

3 Likes

Nice Xenome. Is that interface implemented only twice? Can you run the test again with some arbitrarily large number of blueprints implementing that interface?

I see what you’re getting at…

But, running with 20 different blueprints all implementing that same interface gives pretty much the same result, casting remains about 3 ms faster on average:

Cast+call: 87 - 92 ms (i.e. ~0.0089 ms per single cast-and-call)
Interface: 89 - 95 ms (~0.0092 ms per single call)

The overall difference compared to the previous test is due to different viewport size and the additional 19 actors in the scene graph. So, again, only the relative difference between the two methods is of interest.

EDIT: As a sidenote, these results make me happy, because I very much prefer using interfaces. The numbers make it clear that the cost is negligible, so the choice is a matter of preference rather than performance.

EDIT.AGAIN: To clarify, “20 different blueprints” means 20 different BP classes, each one with its own implementation of the interface, and each one represented by a single instance in the scene. None of these classes have any mesh components attached, so it’s essentially just a bunch of null objects being “rendered”.

3 Likes

Thanks xenome for this so cool test. I thought i was using a bit too much cast and would change some of them in an interface system but now i know this not a trouble. A big thanks.

You’re welcome, Fen. It’s good to go Full Geek every now and then :slight_smile:

Great! :slight_smile:

I just wish we could visualize the interfaces/casts/etc with an event graph, blueprints as nodes, lines going everywhere, etc.

You mean like an automatically generated über-graph showing everything that’s going on in a single view?

Yeah… that would be pretty cool and probably a useful tool.

This should then of course be compared to a cast, interface, direct access in a C++ implementation. :wink:
The overhead would be a lot higher with a long hierarchy as well.
A from B from C from D from E, run function interface on A, implemented in B, C, D, E.
Compared to casting to E using a non public/shared function in E.

But as people say in 9999 cases out of 10000 this will not be your problem or why your code is slow.

Yeah, your mileage will vary of course, and there’s no point comparing C++ to BP in terms of raw performance.

So, for the 9999 normal use-cases for blueprints, the answer to the original question is “don’t worry about it”. If you’re dealing with that single remaining performance-critical case, then C++ is the real answer.

I just ran some final tests with an automated frame counter and accumulating deltatimes to get a more accurate average, and the result was 90 ms for interface calls, and 86 ms for cast+call. That’s for 10 000 loops per frame, and I let it run for a total of 1000 frames per test to get the average to stabilize properly at a “true” value.

This gives a difference per single call of a mere 0.4 microseconds (a.k.a. nothing).

Thank you for your efforts Xenome! This is very valuable info, should be added it into the documentation (or the wiki) for future reference! :slight_smile:

Fantastic to get some hard numbers on that! That is what I would expect - the decision to cast vs use an interface is not really about performance, but about architecture. I would only use an interface when you need one - when you have multiple ‘unrelated’ classes that should share some behavior or event. The example I always give is if you want a flame thrower that can ‘burn’ things, you probably want a ‘burnable’ interface that lots of different BPs can implement. If you only care about one thing (e.g. see if it is the player that i hit, and if so, give them a key), then casting is a bit simpler because you don’t have the hassle of making an interface.

A good thing when optimizing stuff is to cache those objects you need a lot, this will safe you those casting that you do over and over again. For example casting to a specific weapon type from the base engine type, you could hold a casted cached value and change the cache when you switch the weapon or drop it. Same applies for the typical Pawn <-> PlayerController relationship.

But I would only doing it if its totally logic in a specific point or easy to do and to maintain or if you are really seeing some peaks when profiling. Take into account that caching gives you also headaches when the cache is not invalidated properly resulting nice bugs :smiley:

Xenome,
You are awesome…thanks…

we need a Mythbusters thread started for running tests like these… :stuck_out_tongue:

I was going to ask about caching in general in UE. I’m coming from Unity where it’s pretty common to cache everything you plan to reference in a script. Does it make a significant difference in Unreal or should I not worry about it?

I’ll add my thanks, Xenome. Well done. After that wall of appreciation I’m surprised I was the first to upvote your post.

This is topic from 2014;
Votes didn’t even exist back then and we should avoid bringing back old threads like this for no reason…