Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug in readdlm with WSL1 causes doctest failure #40352

Closed
quildtide opened this issue Apr 5, 2021 · 2 comments
Closed

Bug in readdlm with WSL1 causes doctest failure #40352

quildtide opened this issue Apr 5, 2021 · 2 comments

Comments

@quildtide
Copy link
Contributor

quildtide commented Apr 5, 2021

Hi; I'm not sure how supported WSL1 is supposed to be in theory.

I noticed an interesting bug that appears in both today's master (commit 58fba2b) and v1.5.3 on WSL1 but does not seem to appear on v1.5.3 on either Windows proper or Linux proper. I am currently unable to use WSL2 for certain reasons, so I am unsure if this bug also appears in WSL2.

EDIT: I forgot that, for certain reasons, I was working on the Windows filesystem instead of the WSL filesystem. I've just did some more testing and it doesn't appear that this bug appears in WSL1 when using the WSL filesystem instead of the Windows filesystem.

Julia Version 1.7.0-DEV.845
Commit 58fba2b356 (2021-04-04 23:29 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: AMD Ryzen 9 3900X 12-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, znver2)

I first noticed that this doctest fails:

Specifically, the last call to readdlm is supposed to return

julia> readdlm("delim_file.txt", ',')
4×2 Matrix{Any}:
 1  "a"
 2  "b"
 3  "c"
 4  "d"

But instead we get

julia> readdlm("delim_file.txt", ',')
6×2 Matrix{Any}:
 1     "a"
 2     "b"
 3     "c"
 4     "d"
 3.0  3.3
 4.0  4.4

MWE

I tried reproducing this outside of the doctest, and I found that the resulting file is indeed bugged. Here's an MWE for reproducing the bug.

using DelimitedFiles

x = [1; 2; 3; 4];
y = [1.1; 2.2; 3.3; 4.4];
z = ["a"; "b"; "c"; "d"];

open("delim_file.txt", "w") do io
    writedlm(io, [x y], ',')
end;

readdlm("delim_file.txt", ',')

open("delim_file.txt", "w") do io
    writedlm(io, [x z], ',')
end;

The content of delim_file.txt is:

1,a
2,b
3,c
4,d
3.0,3.3
4.0,4.4

Here's an MWE for getting non-bug behavior:

using DelimitedFiles

x = [1; 2; 3; 4];
y = [1.1; 2.2; 3.3; 4.4];
z = ["a"; "b"; "c"; "d"];

open("delim_file.txt", "w") do io
    writedlm(io, [x y], ',')
end;

open("delim_file.txt", "w") do io
    writedlm(io, [x z], ',')
end;

The content of delim_file.txt is:

1,a
2,b
3,c
4,d

The sole difference is achieved via omitting the call to readdlm. It seems to me that readdlm's access to delim_file.txt is never properly released.

The MWE, to my knowledge, only works on WSL1 (for certain reasons, I cannot test on WSL2 at the moment).

I have tried to reproduce the bug using plain read and write and have not yet succeeded in this endeavour.

@vtjnash
Copy link
Member

vtjnash commented Apr 5, 2021

Sounds like a WSL1 bug, in that case, which you can try reporting to Microsoft, but I think it is deprecated. It looks like the code calls copy(mmap(_)) on unix and read(_) elsewhere. I wonder if we can just delete the mmap code, since that seems like it may be rather bad anyways, for reasons both of performance and reliability:

julia> @btime readdlm("delim_file.txt", ',', use_mmap=false);
  20.874 μs (98 allocations: 43.84 KiB) # 4x2 sequential
  9.969 ms (240866 allocations: 6.29 MiB) # 1000x4 rand
  1.101 s (24321453 allocations: 632.03 MiB)# 100000x4 rand (7.4Mb)
194.147011 seconds (3.65 G allocations: 92.595 GiB, 5.73% gc time, 0.18% compilation time) # 10000000x6 (1.1Gb)

julia> @btime readdlm("delim_file.txt", ',', use_mmap=true);
  26.393 μs (101 allocations: 43.92 KiB) #4x2 sequential
  10.304 ms (240869 allocations: 6.29 MiB) # 1000x4 rand
  1.091 s (24321456 allocations: 632.03 MiB) # 100000x4 rand
199.144505 seconds (3.65 G allocations: 92.596 GiB, 5.86% gc time, 0.20% compilation time) # 10000000x6 (1.1Gb)

@quildtide
Copy link
Contributor Author

Thanks; your explanation was very helpful towards allowing me to better understand the issue at hand.

Proposal

DelimitedFiles.readdlm should not assume use_map == true even when the Sys.isunix() == true, as there are edge cases where the OS might be Unix-like while the Filesystem is not.

Alternative Proposal

Nothing changes in DelimitedFiles.readdlm, but the doctest in question changes readdlm("delim_file.txt", ',') to readdlm("delim_file.txt", ',', use_mmap=false).

Motivation

I was under the impression that the problem at hand was that WSL1 is an edge case where Julia is told that it is running on Linux (thus Sys.isunix() ==true) but it's possible to access a filesystem that is 100% Windows and is not Unix-like. use_mmap also has different branches depending on if Sys.isunix == true.

In order to determine if this is more of an WSL1 issue or a Julia issue, I decided to test some other "similar" cases:

  • Linux Virtualbox VM with a shared Windows filesystem via Virtualbox Shared Filesystem
  • Linux with a mounted Windows filesystem via CIFS + Windows Share
  • WSL2 with a Windows filesystem

In none of these three test cases did the bug occur, which makes WSL1 more of an edge case than a general case. I think what makes WSL1 weird is that, unlike these other three cases, WSL1 intentionally chooses to make the Windows side of the Filesystem not Unix-like. Microsoft seems to recommend WSL2 over WSL1 except in cases where performance for accessing files on the Windows side of the Filesystem is a priority (https://docs.microsoft.com/en-us/windows/wsl/compare-versions#comparing-features).

However, WSL1 doesn't appear to be the only edge case. Your note regarding mmap helped me find #8891, where at least two different people (in 2014 and 2016 respectively) encountered a similar issue on Mac with an NFS drive (which I'm guessing might be a Windows drive). Seems like a third case of this popping up on Mac

These two edge cases share in common (if I am correct with my previous guess) the situation where the OS is Unix-like but the Filesystem is not.

Other comment

I have particularly noticed the comment in the documentation for DelimitedFiles.readdlm the following note:

On Windows, you may want to specify true [for use_mmap] if the file is large, and is only read once and not written to.

However, I'm not sure if this note is out of date or not. mmap has a special case when Sys.isunix() == false that seems to handle Windows fine from the basic testing I've done, but I could be wrong.

ElOceanografo pushed a commit to ElOceanografo/julia that referenced this issue May 4, 2021
…liaLang#40415)

Increased resilience to edge cases where OS is reported Unix-like but Filesystem is abnormal

Fixes JuliaLang#8891
Fixes JuliaLang#40352
antoine-levitt pushed a commit to antoine-levitt/julia that referenced this issue May 9, 2021
…liaLang#40415)

Increased resilience to edge cases where OS is reported Unix-like but Filesystem is abnormal

Fixes JuliaLang#8891
Fixes JuliaLang#40352
johanmon pushed a commit to johanmon/julia that referenced this issue Jul 5, 2021
…liaLang#40415)

Increased resilience to edge cases where OS is reported Unix-like but Filesystem is abnormal

Fixes JuliaLang#8891
Fixes JuliaLang#40352
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants