Using a switch statement = massive increase in compile time

Greetings!

I have a UObject that contains an array of structures:

        USTRUCT(BlueprintType)
        struct TEST_API FTestStruct
        {
        	GENERATED_USTRUCT_BODY()
        	UPROPERTY(EditAnywhere, BlueprintReadOnly)
        	FText name;
        
        	UPROPERTY(EditAnywhere, BlueprintReadOnly)
        	FText description;
    
    	        UPROPERTY()
    	        int32 id;
        }

In order to set the string literals for the FText values, I created a function which is basically a switch statement with about 500 values in it. Before I added the function, my project was compiling in about 17 seconds. After I added the function, my project compiled in about 33 minutes.

I commented out the function and the project compiled again in about 17 seconds. I then basically made the switch statement 168 values by commenting out the rest. My project compiled in about 60 seconds. I then pushed the number up to 200 and the project compiled in 230 seconds.

I understand compiling times get longer as projects get larger, but going from 17 seconds to 33 minutes seems a bit excessive giving that I used a very basic switch statement. The increase also seems exponential which seems … weird.

Does anyone know what is going on here? Thanks!

Can you post an example of your switch statement and the build log? Where do you see it hanging the longest? During the UBT generating code, or when it actually starts compiling .cpp files/linking?

Thanks for the response!

The switch statement goes something like:

void UTestObject::InitStaticVariables(int32 index, int32 id)
{
    
    switch (id)
    {
    	case 0:
    		TestArray[index].name = NSLOCTEXT("TestName", "0", "Name Test0");
    		TestArray[index].description = NSLOCTEXT("TestName", "0", "Desc Test0");
			TestArray[index].id = id;
    		break;
    	case 1:
    		TestArray[index].name = NSLOCTEXT("TestName", "1", "Name Test1");
    		TestArray[index].description = NSLOCTEXT("TestName", "1", "Desc Test1");
			TestArray[index].id = id;
	}
}

It seems to hang on compiling the .cpp of the object the switch statement is in:

Warning: Starting HotReload took 0.0s.
CompilerResultsLog: New page: Compilation - Aug 20, 2015, 3:32:09 AM
CompilerResultsLog: Info Compiling game modules for hot reload
CompilerResultsLog: Info Parsing headers for TestEditor
CompilerResultsLog: Info Reflection code generated for TestEditor
CompilerResultsLog: Info Performing 2 actions (4 in parallel)
CompilerResultsLog: Info UTestObject.cpp
CompilerResultsLog: Info [2/2] Link UE4Editor-Test-5672.dll
CompilerResultsLog: Info Creating library […]
CompilerResultsLog: Info -------- End Detailed Actions Stats -----------------------------------------------------------
CompilerResultsLog: Info Total build time: 54.02 seconds
LogMainFrame: MainFrame: Module compiling took 54.304 seconds

Hrm.

Huh, I’m really at a lost. I don’t know why that would cause compiler issues, if that is indeed where this is happening (and it seems like it). Since you are using this code like an array, could you just use that? Or a Set/Map?

I ended up deleting the UObject and created a new one for testing purposes. For some reason, this improved compilation time significantly.

I also did some other testing. The switch statement itself isn’t increasing compilation time, it is the NSLOCTEXT(" ", " ", " ") macro.

Each case in my switch statement was basically setting three text variables. So, that was about 1600 NSLOCTEXT() macro calls. Removing one macro would significantly decrease compilation time in a non-linear way. This can be an issue with macros and Visual Studio:

https://social.msdn.microsoft.com/forums/vstudio/en-US/9a45312e-ba64-44c5-9d65-a9aa09bb815c/slow-compilation-with-macros-in-vc-2010

Anyways, long story short, if someone is going to set a bunch of FText variables with the NSLOCTEXT macro, he or she should probably expect compilation time to significantly increase.

Thanks AdeptStrain for trying to help out!

The problem is being caused by the large number of additional subexpressions created by the NSLOCTEXT macro. VC has an optimisation pass which tries to eliminate common subexpressions, and the time taken to do this is exponential on the number of equivalent subexpressions in the function.

You can fix it by splitting up your functions into smaller pieces (tricky, when it’s a switch) or by disabling optimisations around that function by using these macros:

PRAGMA_DISABLE_OPTIMIZATION
void UTestObject::InitStaticVariables(int32 index, int32 id)
{
}
PRAGMA_ENABLE_OPTIMIZATION

Steve

Oh, awesome. That definitely speeds up compiling!