-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Avoid unnecessary calls to stat within NSURLDirectoryEnumerator #2193
Conversation
…erator fts_read calls stat internally to determine the type of each file that is visited. If URL(fileURLWithPath:) is called with a path that doesn't end with a slash, it calls stat to determine whether the path represents a file or a directory. We know from the FTSENT's fts_info field whether the entry represents a file or a directory, so we can instead call URL(fileURLWithPath:isDirectory:) and avoid the second stat call. This reduces the runtime of FileManager.enumerator(at:includingPropertiesForKeys:options:errorHandler:) by around 40%.
@swift-ci test |
This looks great. For anyone new to the issue, It should be easy to benchmark the difference, and see how Swift’s file enumeration compares to Python’s, with these two scripts: https://github.com/algal/get_files What got us wondering about this was the finding that Python’s os.walk is faster than Foundation’s enumerate method. |
@swift-ci test linux |
Since this PR concerns performance of Foundation's file enumeration routine One issue is what is addressed by this PR, that Foundation calls However, a separate issue may be that Foundation is calling The Python implementation is not based on So one further refinement, if there's appetite for it, might be to refactor |
That's interesting info, I hadn't heard of After a re-reading of the |
I briefly looked at using It's worth noting that after this change After this change, around 1/3 of the runtime is spent doing work that isn't related to walking the filesystem. |
It looks like |
|
The directory flag
|
Yeah, I'd misunderstood
I've confirmed that directories are correctly reported via Should I go ahead and include the |
Yeah it seems like an easy win if it passes all the tests - doesn't look like |
…erator The FTS_NOSTAT flag indicates to fts_read that the caller is not interested in the fts_statp field of the FTSENT structure, allowing fts_read to skip calling stat in some circumstances. This reduces the runtime of FileManager.enumerator(at:includingPropertiesForKeys:options:errorHandler:) by a further 25%.
Done. The relevant tests pass locally for me. |
@swift-ci please test |
fts_read
callsstat
internally to determine the type of each file that is visited. IfURL(fileURLWithPath:)
is called with a path that doesn't end with a slash, it callsstat
to determine whether the path represents a file or a directory. TheFTSENT
'sfts_info
field tells us whether the entry represents a file or a directory, so we can instead useURL(fileURLWithPath:isDirectory:)
and avoid the secondstat
.Additionally, the
FTS_NOSTAT
flag indicates tofts_read
that the caller is not interested in thefts_statp
field of theFTSENT
structure, allowingfts_read
to skip callingstat
in some circumstances.These two changes reduce the runtime of
FileManager.enumerator(at:includingPropertiesForKeys:options:errorHandler:)
by around 55%.