x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

C++ TArray Reference performance slow in 4.8 + 4.9

I am having a performance issue with a TArray of structs, after upgrading from 4.7.5 to 4.8.3.

I'm passing a the reference to the array to a function in a function library, which was working and performing fine in 4.7, but in 4.8 and 4.9, there is a significant hit to performance.

I am a bit new to c++, so if anyone can see anything obvious, please tell me.

The Struct is declared in the same file, while the array is sent from blueprint.

 FST_Hex UGameUtilFunctionLibrary::CubeToHex(FVector CubeCoord, const TArray<FST_Hex>& Hexes, int32 GridXCount)
 {
     FST_Hex Hex;

     bool Found = false;
     FVector2D OffsetCoords = ConvertCubeToOffset(CubeCoord);
     int32 Index = GetHexIndex(OffsetCoords, GridXCount);
     if (HexIndexValid(Hexes, Index))
     {
         GetHex(Hexes, Index, Found, Hex);
     }

     return Hex;
 }

Product Version: UE 4.9
Tags:
more ▼

asked Sep 03 '15 at 01:21 PM in C++ Programming

avatar image

DekanTrue
28 4 7 10

avatar image plangton Sep 03 '15 at 02:35 PM

it is good to send the code of the following functions GetHexIndex and GetHex

avatar image DekanTrue Sep 03 '15 at 02:49 PM
 int32 UGameUtilFunctionLibrary::GetHexIndex(FVector2D OffsetCoord, int32 GridXCount)
 {
     int32 GridWidth = (GridXCount - (GridXCount % 2)) / 2 - 1;
     int32 Index = GetGridIndex(GridWidth, FMath::FloorToInt(OffsetCoord.X), FMath::FloorToInt(OffsetCoord.Y), true);
     Index = Index - (FMath::FloorToInt(OffsetCoord.Y) / 2 * ((GridXCount + 1) % 2));
     return Index;
 }
 
 void UGameUtilFunctionLibrary::GetHex(const TArray<FST_Hex>& Hexes, const int32 Index, bool &Found, FST_Hex &Hex)
 {
     Found = HexIndexValid(Hexes, Index);
     if (Found) {
         Hex = Hexes[Index];
     }
 }
avatar image DekanTrue Sep 03 '15 at 02:55 PM
 bool UGameUtilFunctionLibrary::HexIndexValid(const TArray<FST_Hex>& Hexes, int32 Index)
 {
     bool valid = (Index < Hexes.Num()) && (Index >= 0);
     return valid;
 }
(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

I see no issues with this code. but it might be that filling and reading through your array is causing this in other parts of your code.

However I suggests you the following modification. you are using too much functions for a validity check. TArray already has a simple function for it name isValidIndex : https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Containers/TArray/index.html

 FST_Hex UGameUtilFunctionLibrary::CubeToHex(FVector CubeCoord, const TArray<FST_Hex>& Hexes, int32 GridXCount)
  {
      FVector2D OffsetCoords = ConvertCubeToOffset(CubeCoord);
      int32 Index = GetHexIndex(OffsetCoords, GridXCount);
      
      if ( Hexes.IsValidIndex(Index) )
      {
          return Hexes[Index];
      }
  
      return NULL; // it is safer that Hex as an object
  }

and you can remove two of your functions

more ▼

answered Sep 03 '15 at 03:11 PM

avatar image

plangton
367 17 20 32

avatar image DekanTrue Sep 03 '15 at 03:17 PM

I didn't know that the TArray had that function. Thank you.

I made an isolated test, and problem definitely occurs with the passing of the array. I just don't understand why this has such a large performance hit in 4.8 and up. I tried just returning the Index insted, and then do the rest in blueprint, which caused no performance hit.

avatar image plangton Sep 03 '15 at 03:30 PM

I suggest you once clean the project and rebuild it

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

I don't see anything intensive in this code, you not even interacting with TArray really, atleast not in a way that it would effect performence. How do you know that performance dropped?

You can try to pin point what is taking most time using profiler, which you can find in Window -> Session Frontend. In order plug your code in to it first in ProjectName.h (projectname is name of your project) decler stat group

 DECLARE_STATS_GROUP(TEXT("Project Name Stats"), STATGROUP_ProjectName, STATCAT_ProjectName)

Now in code you want to messure time of execution you place:

 DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Some name of stat that will be displayed"), STAT_ProjectName_NameOFStat, STATGROUP_ProjectName);

You place in specific scope you want to messure, scope is code field that you mark with bracets { } if you place decleration in specific { } it will messure execution time only for code that is in { }. C++ let you create dummy scope (without "if" or "for" etc.) and stat system will acknowledge that, so for example:

 void UGameUtilFunctionLibrary::SomeFunction()
  {
     FunctionA();
 
     {
        DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Some name of stat that will be displayed"), STAT_ProjectName_NameOFStat, STATGROUP_ProjectName);
 
        FunctionB();
        FunctionC();
 
     }
  }

Profiler will only messure FunctionB and FunctionC execution time

Also here you got profiler docs: https://docs.unrealengine.com/latest/INT/Engine/Performance/Profiler/index.html

more ▼

answered Sep 03 '15 at 03:26 PM

avatar image

Shadowriver
37.8k 937 172 1123

avatar image DekanTrue Sep 03 '15 at 03:47 PM

I haven't made a session profile yet. I will do that now. I have only been using the stat unitgraph for monitoring the framerate. If I ran the function on tick, in 4.7.5 the game frame time was 5ms. In 4.8.3 its 15ms where the is a noticeable spike.

avatar image plangton Sep 03 '15 at 03:56 PM

And when you deactivate this function the frame rate is again 5ms?

avatar image Shadowriver Sep 03 '15 at 03:58 PM

Hmm i don't know, you code looks ok, you not looping, you only accessing array which is same as reading varable, so study you code with profiler.

The most silent preference killer is memory allocation (when you spawn or create objects) you should avoid that if doing so in Tick

If you adding items array sometimes TArray need to reallocate the array in memory if array does not fit in specific segment of memory anymore and as i said above memory allocation takes preformence. To prevent that you can reserve memory before hand, best you be maximum value of items that you expect array to have, you can do that with this function:

https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Containers/TArray/Reserve/index.html

Thats hints i can give ya ;]

avatar image DekanTrue Sep 03 '15 at 04:08 PM

Yes. I even made a side by side camparion with a 4.7.5, 4.8.3 and 4.9.0 builds with the exact same code. I also tried recreating the function in blueprint, and using the same functions. Somewhat simplified though.alt text

untitled-1.jpg (114.9 kB)
avatar image DekanTrue Sep 03 '15 at 04:25 PM

alt text

I made a few screenshot for comparison the blueprint setup above. I made the function run on tick (Just for testing), and switched it on/off every 2 seconds. The top one is the "cube to hex c++ function". The bottom is the more version where no array reference is passed to c++.

untitled-2.jpg (55.9 kB)
avatar image Shadowriver Sep 03 '15 at 04:28 PM

So CubeToHex tames more time or blueprint? keep in mind that blueprint slower then native code

avatar image DekanTrue Sep 03 '15 at 04:35 PM

The "blueprint" version is just calling the same c++ functions as the cubeToHex function would. Yes my early test showed me blueprint to be 5-10 times slower. But keep in mind that the one without the spikes, are the "blueprint version".

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question