Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save schellingb/4e01412cedbe774a795f77e448887c0d to your computer and use it in GitHub Desktop.
Save schellingb/4e01412cedbe774a795f77e448887c0d to your computer and use it in GitHub Desktop.
UE4 Macro VS Range VS Lambda VS TFunctionRef VS TFunction
#define SpiralForMacro(STARTX, STARTY, CODE) \
{ \
FIntPoint tile = FIntPoint(0, 0), delta = FIntPoint(0, -1); \
for (;;) \
{ \
FIntPoint tc = {(STARTX) + tile.X, (STARTY) + tile.Y}; \
\
{ CODE } \
\
if ((tile.X == tile.Y) || ((tile.X < 0) && (tile.X == -tile.Y)) || ((tile.X > 0) && (tile.X == 1-tile.Y))) \
{ \
/* Reached a corner, turn left */ \
int t = delta.X; \
delta.X = -delta.Y; \
delta.Y = t; \
} \
tile.X += delta.X; \
tile.Y += delta.Y; \
} \
}
FORCENOINLINE void TestMacro(FIntPoint start, int32& count, int32 limit)
{
SpiralForMacro(start.X, start.Y,
{
count += tc.X+tc.Y;
if (tc.X > limit)
return;
})
}
struct SpiralRange
{
FORCEINLINE SpiralRange(FIntPoint start) : Start(start) {}
FORCEINLINE SpiralRange& begin() { return *this; }
FORCEINLINE SpiralRange& end() { return *this; }
FORCEINLINE SpiralRange operator++()
{
if ((Tile.X == Tile.Y) || ((Tile.X < 0) && (Tile.X == -Tile.Y)) || ((Tile.X > 0) && (Tile.X == 1-Tile.Y)))
{
// Reached a corner, turn left
int t = Delta.X;
Delta.X = -Delta.Y;
Delta.Y = t;
}
Tile.X += Delta.X;
Tile.Y += Delta.Y;
return *this;
}
FORCEINLINE bool operator!=(const SpiralRange & other) const { return true; }
FORCEINLINE FIntPoint operator*() const { return {Start.X + Tile.X, Start.Y + Tile.Y}; }
FIntPoint Start, Tile = FIntPoint(0, 0), Delta = FIntPoint(0, -1);
};
FORCENOINLINE void TestRange(FIntPoint start, int32& count, int32 limit)
{
for (FIntPoint tc : SpiralRange(start))
{
count += tc.X+tc.Y;
if (tc.X > limit) break;
}
}
FORCEINLINE static void SpiralForTFRef(FIntPoint start, TFunctionRef<bool(FIntPoint)> func)
{
FIntPoint tile = FIntPoint(0, 0), delta = FIntPoint(0, -1);
for (;;)
{
if (!func({start.X + tile.X, start.Y + tile.Y}))
break;
if ((tile.X == tile.Y) || ((tile.X < 0) && (tile.X == -tile.Y)) || ((tile.X > 0) && (tile.X == 1-tile.Y)))
{
// Reached a corner, turn left
int t = delta.X;
delta.X = -delta.Y;
delta.Y = t;
}
tile.X += delta.X;
tile.Y += delta.Y;
}
}
FORCENOINLINE void TestTFRef(FIntPoint start, int32& count, int32 limit)
{
SpiralForTFRef(start, [&count, limit](FIntPoint tc)
{
count += tc.X+tc.Y;
return (tc.X <= limit);
});
}
FORCEINLINE static void SpiralForTF(FIntPoint start, const TFunction<bool(FIntPoint)>& func)
{
FIntPoint tile = FIntPoint(0, 0), delta = FIntPoint(0, -1);
for (;;)
{
if (!func({start.X + tile.X, start.Y + tile.Y}))
break;
if ((tile.X == tile.Y) || ((tile.X < 0) && (tile.X == -tile.Y)) || ((tile.X > 0) && (tile.X == 1-tile.Y)))
{
// Reached a corner, turn left
int t = delta.X;
delta.X = -delta.Y;
delta.Y = t;
}
tile.X += delta.X;
tile.Y += delta.Y;
}
}
FORCENOINLINE void TestTF(FIntPoint start, int32& count, int32 limit)
{
SpiralForTF(start, [&count, limit](FIntPoint tc)
{
count += tc.X+tc.Y;
return (tc.X <= limit);
});
}
template<typename TLambda> FORCEINLINE static void SpiralForLmb(FIntPoint start, const TLambda& func)
{
FIntPoint tile = FIntPoint(0, 0), delta = FIntPoint(0, -1);
for (;;)
{
if (!func({start.X + tile.X, start.Y + tile.Y}))
break;
if ((tile.X == tile.Y) || ((tile.X < 0) && (tile.X == -tile.Y)) || ((tile.X > 0) && (tile.X == 1-tile.Y)))
{
// Reached a corner, turn left
int t = delta.X;
delta.X = -delta.Y;
delta.Y = t;
}
tile.X += delta.X;
tile.Y += delta.Y;
}
}
FORCENOINLINE void TestLmb(FIntPoint start, int32& count, int32 limit)
{
SpiralForLmb(start, [&count, limit](FIntPoint tc)
{
count += tc.X+tc.Y;
return (tc.X <= limit);
});
}
static int64_t rdtscstart, rdtsccount, rdtsctotal, rdtscmin, rdtscmax, bmresaccum;
void BMRESET()
{
rdtsccount = 0;
rdtsctotal = 0;
rdtscmin = 999999999999;
rdtscmax = 0;
bmresaccum = 0;
}
void BMSTART()
{
rdtscstart = (int64_t)__rdtsc();
}
void BMEND(int32 count)
{
int64_t end = (int64_t)__rdtsc(), res = ((end - rdtscstart) >> 20);
if (res > rdtscmax) rdtscmax = res;
if (res < rdtscmin) rdtscmin = res;
rdtsctotal += res;
rdtsccount++;
bmresaccum += count;
}
void BMFINISH(const TCHAR* msg)
{
FString str = FString::Printf(TEXT("[BM] %s: AVG = %4d, MIN = %4d, MAX = %4d (res: %d)"), msg, (int)(rdtsctotal/rdtsccount), (int)rdtscmin, (int)rdtscmax, (int)bmresaccum);
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(str));
UE_LOG(LogTemp, Warning, TEXT("%s"), *str);
}
FORCENOINLINE void LoopTest()
{
int32 count;
enum { test_reps = 10, test_limit = 3237 };
BMRESET(); for (int i = 0; i != test_reps; i++) { count = 0; BMSTART(); TestMacro(FIntPoint(10,10), count, test_limit); BMEND(count); } BMFINISH(TEXT("Macro"));
BMRESET(); for (int i = 0; i != test_reps; i++) { count = 0; BMSTART(); TestRange(FIntPoint(10,10), count, test_limit); BMEND(count); } BMFINISH(TEXT("Range"));
BMRESET(); for (int i = 0; i != test_reps; i++) { count = 0; BMSTART(); TestLmb (FIntPoint(10,10), count, test_limit); BMEND(count); } BMFINISH(TEXT("Lmb "));
BMRESET(); for (int i = 0; i != test_reps; i++) { count = 0; BMSTART(); TestTFRef(FIntPoint(10,10), count, test_limit); BMEND(count); } BMFINISH(TEXT("TFRef"));
BMRESET(); for (int i = 0; i != test_reps; i++) { count = 0; BMSTART(); TestTF (FIntPoint(10,10), count, test_limit); BMEND(count); } BMFINISH(TEXT("TF "));
}
@schellingb
Copy link
Author

My results:

DebugGame:
  Macro: AVG =  588, MIN =  580, MAX =  596
  Range: AVG = 2083, MIN = 2074, MAX = 2091
  Lmb  : AVG = 2128, MIN = 2118, MAX = 2135
  TFRef: AVG = 1758, MIN = 1755, MAX = 1762
  TF   : AVG = 1900, MIN = 1880, MAX = 1927

Development:
  Macro: AVG =  141, MIN =  141, MAX =  143
  Range: AVG =  246, MIN =  238, MAX =  260
  Lmb  : AVG =  975, MIN =  971, MAX =  986
  TFRef: AVG = 1301, MIN = 1297, MAX = 1304
  TF   : AVG = 1304, MIN = 1299, MAX = 1311

Shipping:
  Macro: AVG =  166, MIN =  166, MAX =  168
  Range: AVG =  255, MIN =  253, MAX =  258
  Lmb  : AVG =  960, MIN =  957, MAX =  966
  TFRef: AVG = 1301, MIN = 1298, MAX = 1309
  TF   : AVG = 1283, MIN = 1279, MAX = 1289

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment