Last active
August 28, 2022 01:01
-
-
Save schellingb/4e01412cedbe774a795f77e448887c0d to your computer and use it in GitHub Desktop.
UE4 Macro VS Range VS Lambda VS TFunctionRef VS TFunction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 ")); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My results: