After a benchmarking discussion in the FSSF slack we found the main culprit for the C# / F# speed differences. tail. was being emitted for a non recursive method, that turns off JIT inlining and other optimizations.
Repro can be found here.
.locals init (
[0] !!a
)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.Generic.List`1<string> _/TailLogger::messages
IL_0006: ldarg.2
IL_0007: stloc.0
IL_0008: ldloca.s 0
IL_000a: constrained. !!a
[...]
The C# IL for the same method completely does away with the arg to local dance and just uses the arg directly.
These extraneous load/store patterns confuse the JITs dataflow analysis whether things are being modified or not, hampering enregistration.
After a benchmarking discussion in the FSSF slack we found the main culprit for the C# / F# speed differences.
tail.was being emitted for a non recursive method, that turns off JIT inlining and other optimizations.Repro can be found here.
https://sharplab.io/#v2:DYLgZgzgNALiCWwA+B7ADgUwHYAIDKAnhDBgLYCwAUOtvkSaQHQBKArljPKRowMIqk0iDACc8ogG7wAxhghUqMAphwAZFAHMNo1RgkZgOALw4AgsZwAGHEhwAhHBYCMOBZSUr1W0QAoAlMZUjo7AGDA43BAQAIbaEBaExGR8KMCh0pwoWBCMAOLYojKMqvDEADzEIvBYGgB8Pk6WTZZ+ANxBwR2OANplALJhABYoACYAkoLAPgMww+OTAPJomdmMploichDw+mNYwNXVGn61ALpdOKHhWOg4/hb+F9ykAEaiOLOlxZo+ofqGIDUmm0Il0/ygEQgGhwgMqRwCRguwQiW1icjWIxGPlIUL8SOCNzQj0oTzIbxEH0GXy8vz0BhhQO8oLpwAhKBeACsGQByaII/GOSIxOIYrHsjmMAAqKDwMCqNX8eMoyORhOJimUGBwkuiiC8IPuiOVwSuKKiaPiJkSDBSaQwGXgWRy+SwhWkxVKMAqcqO9UazTaF1Jr3enxyNL+9MB+p0LIhOOhsJ9NX5xpVZuF6NMmOxuLcyOe5Mp1J+kYBjJBYIMbM5PL5gTTKqFFtFPnFUplyY0iqoQA===
Another smaller codegen issue can be seen in the IL for
ObjLog<'a>The C# IL for the same method completely does away with the arg to local dance and just uses the arg directly.
These extraneous load/store patterns confuse the JITs dataflow analysis whether things are being modified or not, hampering enregistration.
https://sharplab.io/#v2:C4LglgNgNAJiDUAfAAgBgATIIwBYDcAsAFDHIDM6ApgHYCuAtugDID2A5m5QE5OUBulCOmIBvYunQBBKOPQAhYgF9ipCsgBM8gIYBnSqw7dRsiQAcuYPluCVmYHcAA82VAD509Sjp1bOO9AC86NSUAO52Ds5YbgAU0agJAJSERBISJphqOMzsMQacPPyC6BBF0JjRHjpsiRliqWmNnt6+XgB0kjAwMfTVyRnKJA0S5JjZBo4AKq557AW8AkKli1Dok+gsAEYAVrXD6PWNTV4+fh1dMVvbbZMsAMrAFtRsMYn9+4OKQA=
If anything the focus should be on making sure
tail.is only ever emitted for real recursive methods/functions