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

PathRef for directories is filesystem-dependent and not reproducible #1808

Closed
atty303 opened this issue Apr 1, 2022 · 4 comments · Fixed by #1992
Closed

PathRef for directories is filesystem-dependent and not reproducible #1808

atty303 opened this issue Apr 1, 2022 · 4 comments · Fixed by #1992
Milestone

Comments

@atty303
Copy link
Contributor

atty303 commented Apr 1, 2022

The hashCode of PathRef returns a value that depends on the file listing order of the file system.

for ((path, attrs) <- os.walk.attrs(path, includeTarget = true, followLinks = true)) {
digest.update(path.toString.getBytes)
if (!attrs.isDir) {
if (isPosix) {
updateWithInt(os.perms(path, followLinks = false).value)
}
if (quick) {
val value = (attrs.mtime, attrs.size).hashCode()
updateWithInt(value)
} else if (jnio.Files.isReadable(path.toNIO)) {
val is = os.read.inputStream(path)
StreamSupport.stream(is, digestOut)
is.close()
}
}

os.walk uses DirectoryStream, which returns a list of files in an indefinite order depending on the file system.

The elements returned by the iterator are in no specific order. Some file systems maintain special links to the directory itself and the directory's parent directory. Entries representing these links are not returned by the iterator.

As a concrete example, if an out directory is copied across machines in a Linux+XFS environment, the cache will be invalidated because the order in which files are stored changes. Note that ext4 hides this problem because it returns a stable file list.

I think mill should compute hashCode by sorting instead of filesystem-dependent order.

File listing order in XFS

$ touch a
$ touch b
$ ls -f
.  ..  a  b

$ touch b
$ touch a
$ ls -f
.  ..  b  a

File listing order in EXT4

$ touch a
$ touch b
$ ls -f
b  .  a  ..

$ touch b
$ touch a
$ ls -f
b  .  a  ..
@lefou
Copy link
Member

lefou commented Apr 1, 2022

I think, there is no Java API available, which is able to return a sorted recursive directory stream. So, we need to fall back to some self implemented directory traversal which may be less performant and may need more memory. Maybe, it could be hidden behind some settings (env variable?) or detected based on the filesystem type and/or OS?

As this affects Mill cache correctness and reproducibility, we definitely will accept a PR.

@Sailsman63
Copy link

Hmm... could this return different hashes in the same run if the file got pulled in two different ways? (Diamond dependency) If so, that might explain the multi-hash thing that I was experiencing here

@lefou
Copy link
Member

lefou commented Apr 4, 2022

@Sailsman63 I doubt that, as the mill dependency graph is a DAG (https://en.wikipedia.org/wiki/Directed_acyclic_graph) which is calculated once at the start of a Mill evaluation. So targets won't run more than one time. The hashCode of PathRef isn't unstable pe se but it might not be reproducible, so it only affects the change detection for cached targets. Meaning, we may miss-interpret some cache hits as cache faults.

@lefou lefou changed the title PathRef returns unstable hashCode PathRef for directories is filesystem-dependent and unstable Apr 8, 2022
@lefou lefou changed the title PathRef for directories is filesystem-dependent and unstable PathRef for directories is filesystem-dependent and not reproducible Apr 8, 2022
@atty303
Copy link
Contributor Author

atty303 commented May 17, 2022

I changed my CI to Ext4 to mitigate this problem ande now I am not in trouble.
I'll try to create a PR when i have time!

atty303 added a commit to atty303/mill that referenced this issue Aug 15, 2022
lefou pushed a commit that referenced this issue Aug 15, 2022
@lefou lefou added this to the 0.10.6 milestone Aug 15, 2022
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

Successfully merging a pull request may close this issue.

3 participants