Currently developing futuristic smart-device, IoT connected, highway construction site safety system in EU.
Used to work on infrastructure, application architecture and cloud engineering.
Woah, this looks so clean.
From the code execution and efficiency point of view it's a nightmare. Instead of using full potential of your CPU you're making it sub-optimal the least by abusing function calls.
In normal situation you'd store the parameters in available registers or push them to the heap, store the stack pointer, redirect the code by updating the instruction pointer, use generic add instruction multiple times and then call return and remove the address from stack.
With curry function you're doing this multiple times increasing nesting, filling the stack (I don't want to debug this by looking at the stack trace, must look like a mess), making the code more vulnerable to thread unsafety as there is much more room when the thread can be pre-empted.
I can't see a reason why would anyone use this in production code. I assume any good compiler would inline those function calls anyways leaving you with significantly different debug and production code which might result in weird bugs that you cannot reproduce.
Currently developing futuristic smart-device, IoT connected, highway construction site safety system in EU.
Used to work on infrastructure, application architecture and cloud engineering.
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<BenchmarkNormalVsCurry>();
}
}
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
[RPlotExporter]
public class BenchmarkNormalVsCurry
{
public static int NormalAdd(int a, int b, int c, int d)
{
return a + b + c + d;
}
public static Func<int, Func<int, Func<int, int>>> CurryAdd(int a) =>
(b) =>
(c) =>
(d) => a + b + c + d;
[Benchmark]
public void TestNormalAdd() => NormalAdd(1, 2, 3, 4);
[Benchmark]
public void TestCurryAdd() => CurryAdd(1)(2)(3)(4);
}
Fantastic that you emphasize this. While FP code constructs unclutter the code, without proper tool support you just move the clutter into the runtime.
Indeed, JavaScript (nor C#) was never designed to go full throttle on functional programming concepts. Therefor the JIT compiler doesn't optimize any of it.
Languages like Haskell, F#, Erlang, Lisp, are built for this, and will handle it in a better way.
I'm definitely interested to know what happens behind all the functions and about compilation. However, I'm not quite experienced at it, but hopefully this will be helpful to others and even me in future.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Woah, this looks so clean.
From the code execution and efficiency point of view it's a nightmare. Instead of using full potential of your CPU you're making it sub-optimal the least by abusing function calls.
In normal situation you'd store the parameters in available registers or push them to the heap, store the stack pointer, redirect the code by updating the instruction pointer, use generic
add
instruction multiple times and then callreturn
and remove the address from stack.With curry function you're doing this multiple times increasing nesting, filling the stack (I don't want to debug this by looking at the stack trace, must look like a mess), making the code more vulnerable to thread unsafety as there is much more room when the thread can be pre-empted.
I can't see a reason why would anyone use this in production code. I assume any good compiler would inline those function calls anyways leaving you with significantly different debug and production code which might result in weird bugs that you cannot reproduce.
Normal function in IL:
Curry function in IL:
Benchmark:
the program:
Fantastic that you emphasize this. While FP code constructs unclutter the code, without proper tool support you just move the clutter into the runtime.
Indeed, JavaScript (nor C#) was never designed to go full throttle on functional programming concepts. Therefor the JIT compiler doesn't optimize any of it.
Languages like Haskell, F#, Erlang, Lisp, are built for this, and will handle it in a better way.
Thanks man, for putting this out here!
I'm definitely interested to know what happens behind all the functions and about compilation. However, I'm not quite experienced at it, but hopefully this will be helpful to others and even me in future.