About creating variables in tick function (and performance)

Hello there,
I was following the “CryptRider” tutorial of the “Unreal 5.0 C++ Developer: Learn C++ and Make Video Games” course after the “GetWorld()” video.

I see that the GetWorld() method gets called in Tick(), and then the UWorld* ptr is used to print some data. I don’t remember if the result gets stored in a UWorld* local variable, but this doesn’t change much, as GetWorld() is still called every frame, and returns a pointer very frame.

The operation itself is not expensive, as GetWorld() is just returning a pointer to “World”, but it’s getting called every frame.
Shouldn’t it be better to just declare a UWorld* pointer variable inside our class and use the BeginPlay method to assign it to the GetWorld() returned ptr only once?
We should be able to access the UWorld using our pointer, but without recalculating it every time.

Or there is no sense in doing what I am saying?

Aren’t we saving some calculations?

The compiler will almost certainly optimise the function call away and just access it directly, and indeed, trying just now to step into GetWorld() on that line with the debugger just steps over it.

So you would just end up storing two copies of World, one inherited from UActorComponent and the one you would be storing in UGrabber

Thank you very much, DanM! Super clear and makes sense.

Do you have some suggestions or resources to get a deeper knowledge of this stuff (e.g., knowing how the compiler optimizes things like this)!

Thank you!

Having now looked at the function and disassembly, storing it yourself might save an instruction or two.

Visual Studio is showing me the disassembly for that line is

	float Time = GetWorld()->TimeSeconds;
00007FFD949C6C18  mov         rax,qword ptr [rdi+0B8h]  
00007FFD949C6C1F  test        rax,rax  
00007FFD949C6C22  jne         UGrabber::TickComponent+4A4h (07FFD949C6C34h)  
00007FFD949C6C24  mov         rcx,rdi  
00007FFD949C6C27  call        qword ptr [__imp_UActorComponent::GetWorld_Uncached (07FFD949D1D68h)]  
00007FFD949C6C2D  mov         rdx,qword ptr [__imp_LogTemp (07FFD949D11F8h)]  
00007FFD949C6C34  movss       xmm0,dword ptr [rax+6E8h]  
00007FFD949C6C3C  movss       dword ptr [rsp+28h],xmm0  

Which if I’m not mistaken (x86 noob), put the value of WorldPrivate into the rax register then test it with itself which would clear the Zero Flag (ZF) if it’s 0 (null here), then if ZF is 0 it will jump to the second to last line, which puts TimeSeconds into a register.

So if you made a member variable for it then you would save the test and jump (unless you then add checks to see if your variable is non-null).

I’m not sure if this is what you’re looking for exactly but it’s a great talk nonetheless

There’s also (all of Scott’s CPPCon and GoingNative talks are great)

I can’t find it now but I remember seeing a talk by Herb Sutter in a similar vein to the last one

1 Like

Thank you very much for the explanation and the resources!
I will try to learn understanding and reading the disassembly as well, as it seems useful when doing performance fine-tuning and/or learning what’s happening under the hood.

Also thanks for the videos, I will watch them for sure!

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms