BenchmarkDotNet icon indicating copy to clipboard operation
BenchmarkDotNet copied to clipboard

Unable to benchmark with Mono runtime on Linux

Open Windows10CE opened this issue 2 years ago • 3 comments
trafficstars

Benchmarking using Mono as a runtime on Linux seems to be broken since 0.13.3, with an error message saying "The Roslyn toolchain is only supported on .NET Framework". This leads me to believe that #2120 is the cause for the issue. Simply downgrading to 0.13.2 allows the benchmark to run as expected, and is correctly reported as using the Mono runtime.

Minimal repro (just needs the .NET 7 SDK to build and Mono to run): BDNMinimalRepro.zip

Windows10CE avatar Apr 29 '23 08:04 Windows10CE

@Windows10CE thanks for the bug report! Indeed, the Mono support on Linux has been broken since v0.13.3. If we remove the "The Roslyn toolchain is only supported on .NET Framework" validation, we will discover that the actual problem is caused by anonymous pipes that were introduced in v0.13.3:

Unhandled Exception:
System.IO.IOException: Invalid handle to path "[Unknown]"
  at System.IO.FileStream.Init (Microsoft.Win32.SafeHandles.SafeFileHandle safeHandle, System.IO.FileAccess access, System.Boolean ownsHandle, System.Int32 bufferSize, System.Boolean isAsync, System.Boolean isConsoleWrapper) [0x0006a] in <de882a77e7c14f8ba5d298093dde82b2>:0 
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, System.Int32 bufferSize, System.Boolean isAsync) [0x00011] in <de882a77e7c14f8ba5d298093dde82b2>:0 
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, System.Int32 bufferSize) [0x00000] in <de882a77e7c14f8ba5d298093dde82b2>:0 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(Microsoft.Win32.SafeHandles.SafeFileHandle,System.IO.FileAccess,int)
  at BenchmarkDotNet.Engines.AnonymousPipesHost.OpenAnonymousPipe (System.String fileHandle, System.IO.FileAccess access) [0x00011] in <752c4abba0be4396bb787413596bc67e>:0 
  at BenchmarkDotNet.Engines.AnonymousPipesHost..ctor (System.String writHandle, System.String readHandle) [0x00006] in <752c4abba0be4396bb787413596bc67e>:0 
  at BenchmarkDotNet.Autogenerated.UniqueProgramName.AfterAssemblyLoadingAttached (System.String[] args) [0x0000c] in <f86452cd291f4212bc49ff000eb478bc>:0 
  at BenchmarkDotNet.Autogenerated.UniqueProgramName.Main (System.String[] args) [0x00000] in <f86452cd291f4212bc49ff000eb478bc>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.IOException: Invalid handle to path "[Unknown]"
  at System.IO.FileStream.Init (Microsoft.Win32.SafeHandles.SafeFileHandle safeHandle, System.IO.FileAccess access, System.Boolean ownsHandle, System.Int32 bufferSize, System.Boolean isAsync, System.Boolean isConsoleWrapper) [0x0006a] in <de882a77e7c14f8ba5d298093dde82b2>:0 
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, System.Int32 bufferSize, System.Boolean isAsync) [0x00011] in <de882a77e7c14f8ba5d298093dde82b2>:0 
  at System.IO.FileStream..ctor (Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.IO.FileAccess access, System.Int32 bufferSize) [0x00000] in <de882a77e7c14f8ba5d298093dde82b2>:0 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(Microsoft.Win32.SafeHandles.SafeFileHandle,System.IO.FileAccess,int)
  at BenchmarkDotNet.Engines.AnonymousPipesHost.OpenAnonymousPipe (System.String fileHandle, System.IO.FileAccess access) [0x00011] in <752c4abba0be4396bb787413596bc67e>:0 
  at BenchmarkDotNet.Engines.AnonymousPipesHost..ctor (System.String writHandle, System.String readHandle) [0x00006] in <752c4abba0be4396bb787413596bc67e>:0 
  at BenchmarkDotNet.Autogenerated.UniqueProgramName.AfterAssemblyLoadingAttached (System.String[] args) [0x0000c] in <f86452cd291f4212bc49ff000eb478bc>:0 
  at BenchmarkDotNet.Autogenerated.UniqueProgramName.Main (System.String[] args) [0x00000] in <f86452cd291f4212bc49ff000eb478bc>:0 

I tried various ways to set up a simple AnonymousPipeServerStream-based demo for communication between two processes using Mono 6.12.0.182 on Linux, but it seems this API is broken on the runtime level (or it has some unobvious usage limitations).

The only solution I have in mind is to recover the old communication behavior based on the console output parsing as a backup workaround for the Linux+Mono case. However, it would force us to support two communication protocols and will lead to the increased complexity of the BenchmarkDotNet execution toolchain.

@adamsitnik do you have any ideas of how to make AnonymousPipeServerStream work on Linux+Mono?

AndreyAkinshin avatar May 02 '23 17:05 AndreyAkinshin

I'm not sure if this mono issue is helpful here. https://github.com/mono/mono/issues/18100

timcassell avatar Aug 25 '23 00:08 timcassell

@timcassell it's very useful! It shows that it's not a bug on BDN, but Mono side (Mono closes the pipe file descriptor and there is nothing we can do about it)

However, it would force us to support two communication protocols and will lead to the increased complexity of the BenchmarkDotNet execution toolchain.

I don't think it's worth it. 0.13.3 was released 8 months ago and we have received only one bug report so far.

We could address that by using NoAcknowledgementConsoleHost for the old Mono on Linux, which is already used for WASM:

https://github.com/dotnet/BenchmarkDotNet/blob/e0c667f6363e75f4e18e34767b6211d360962873/src/BenchmarkDotNet/Templates/BenchmarkProgram.txt#L31

It would simply disable the possibility to respond to "events", but since we don't support many diagnosers for old Mono anyway, it should not be an issue.

adamsitnik avatar Aug 25 '23 07:08 adamsitnik