BenchmarkDotNet icon indicating copy to clipboard operation
BenchmarkDotNet copied to clipboard

PathTooLongException with benchmark that has long parameter

Open jakobbotsch opened this issue 2 years ago • 13 comments

The following invocation in dotnet/performance:

dotnet run -c Release -f net7.0 -- --filter "System.Numerics.Tests.Perf_BigInteger.Parse" --corerun /mnt/c/dev/dotnet/core_roots/cf2187_release/corerun -p EP

hangs on a benchmark with a very long parameter. When I ctrl-C it, I get the following:

An exception occurred during reading trace stream: System.IO.PathTooLongException: The path '/home/jakob/dev/dotnet/performance/artifacts/bin/MicroBenchmarks/Release/net7.0/BenchmarkDotNet.Artifacts/System.Numerics.Tests.Perf_BigInteger.Parse(numberString_ 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890)-20220830-133655.nettrace' is too long, or a component of the specified path is too long.
   at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirError)
   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, UnixFileMode openPermissions, Int64& fileLength, UnixFileMode& filePermissions, Func`4 createOpenException)
   at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
   at BenchmarkDotNet.Diagnosers.EventPipeProfiler.CopyEventStreamToFile(EventPipeSession session, String fileName, ILogger logger)
ExitCode != 0 and no results reported

Seems like BDN is trying to include all the parameters in the file name of the event pipe trace.

jakobbotsch avatar Aug 30 '22 11:08 jakobbotsch

Hi @jakobbotsch

Thank you for detailed bug report.

I currently don't have the time to look at, so I am going to make it "up-for-grabs" hoping that someone else will. The bug is somewhere in the following method: https://github.com/dotnet/BenchmarkDotNet/blob/master/src/BenchmarkDotNet/Helpers/ArtifactFileNameHelper.cs#L18

To work around this bug you need get rid of [Arguments/ArgumentsSource/Params/ParamsSource] usage. Example:

private readonly BigIntegerData arg1 = new BigIntegerData("123");
private readonly BigIntegerData arg2 = new BigIntegerData(int.MinValue.ToString());
private readonly BigIntegerData arg2 = new BigIntegerData(string.Concat(Enumerable.Repeat("1234567890", 20)));

[Benchmark] public BigInteger Parse1() => BigInteger.Parse(arg1.Text);
[Benchmark] public BigInteger Parse2() => BigInteger.Parse(arg2.Text);
[Benchmark] public BigInteger Parse2() => BigInteger.Parse(arg3.Text);
dotnet run -c Release -f net7.0 -- --filter "System.Numerics.Tests.Perf_BigInteger.Parse*" --corerun /mnt/c/dev/dotnet/core_roots/cf2187_release/corerun -p EP

adamsitnik avatar Aug 30 '22 13:08 adamsitnik

@adamsitnik I'd be interested in working on this. How far away is 0.13.3?

SeanFarrow avatar Sep 19 '22 16:09 SeanFarrow

@jakobbotsch Which directory were you running this in specifically? did you have any docker container or mounts set up?

SeanFarrow avatar Sep 19 '22 17:09 SeanFarrow

I think I was running the command inside /home/jakob/dev/dotnet/perforamnce/src/benchmarks/micro.

jakobbotsch avatar Sep 19 '22 18:09 jakobbotsch

I'd be interested in working on this.

@SeanFarrow great, I've assigned you.

How far away is 0.13.3?

I would like to release it within a month, as it's going to contain some important bugfixes.

adamsitnik avatar Sep 20 '22 13:09 adamsitnik

@adamsitnik Thanks, I'll start work this weekend.

What do we want as the behaviour if the path is too long? Currently as per the bug report, we are thrrowing an exception, short we just shorten th path to somethingthat is acceptable? Finally, wha is the easiest way of debugging a benchmark, assuming I'm running using corerun?

SeanFarrow avatar Sep 22 '22 05:09 SeanFarrow

is this still an open/unresolved issue?

saad995 avatar Oct 07 '22 17:10 saad995

@adamsitnik @saad995 It will be in the next few minutes, unfortunately, we have a family illness/emergency meaning I can't do as much outside of work as I would like.

Do you want me to push my branch with some tests?

Thanks, Sean.

SeanFarrow avatar Oct 08 '22 06:10 SeanFarrow

@SeanFarrow yes please, that would be helpful...I will look into it tomorrow. if it's possible for me to continue on this fix I will let you guys know.

saad995 avatar Oct 08 '22 08:10 saad995

@saad995 The fork is at: https://github.com/SeanFarrow/benchmarkdotnet.git the branch you want to start with is: bugfix/sf/2093-fix-path-too-long-exception I'll leave the fork there for a few days, so if you could let me know when you have it, I can then delete it.

Thanks, Sean.

SeanFarrow avatar Oct 08 '22 08:10 SeanFarrow

For whoever will work on this, it looks like Windows has an escape hatch for very long paths, but it requires parsing the path to make sure it has proper formatting manually. Pre-pending the path with \\?\ allows up to 32,767 characters instead of 260. See the StackOverflow answers for details. More Reading

Not sure if we want to go down that path (pun not intended).

[Edit] I am surprised it's failing on net7.0, as there are claims that long paths are automatically handled in Core already.

timcassell avatar Jul 08 '23 04:07 timcassell

@timcassell since BenchmarkDotNet toolchains involve other tools (like MSBuild or profilers) and these tools may not support long paths, it doesn't make a lot of sense to introduce hacks with \\?\ to workaround the long path problem. I would suggest working on shortification of the existing paths we generate.

AndreyAkinshin avatar Jul 08 '23 11:07 AndreyAkinshin

From what I see,

https://github.com/dotnet/BenchmarkDotNet/blob/6fa7a91444b01029cc2ed81c90e237ae3e36c595/src/BenchmarkDotNet/Helpers/ArtifactFileNameHelper.cs#L27-L31

The long names due to parameters already handled by code. My guess that observed issue is due to fact that code run under WSL, but mounted filesystem run under Windows. So BDN calculate path limit to 1024 characters, while FS supports only ~260.

kant2002 avatar Jul 25 '23 19:07 kant2002