Skip to content

os.DirEntry.is_junction can be ~twice as fast #108717

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

Closed
sobolevn opened this issue Aug 31, 2023 · 0 comments · Fixed by #108718
Closed

os.DirEntry.is_junction can be ~twice as fast #108717

sobolevn opened this issue Aug 31, 2023 · 0 comments · Fixed by #108718
Assignees
Labels
extension-modules C modules in the Modules dir performance Performance or resource usage

Comments

@sobolevn
Copy link
Member

sobolevn commented Aug 31, 2023

Right now it is implemented as:

cpython/Modules/posixmodule.c

Lines 14566 to 14583 in 79823c1

/*[clinic input]
os.DirEntry.is_junction -> bool
defining_class: defining_class
/
Return True if the entry is a junction; cached per entry.
[clinic start generated code]*/
static int
os_DirEntry_is_junction_impl(DirEntry *self, PyTypeObject *defining_class)
/*[clinic end generated code: output=7061a07b0ef2cd1f input=475cd36fb7d4723f]*/
{
#ifdef MS_WINDOWS
return self->win32_lstat.st_reparse_tag == IO_REPARSE_TAG_MOUNT_POINT;
#else
return 0;
#endif
}

Removing unused defining_class: defining_class from clinic has one big adavantage (aside from the fact that it is unused in the first place): it speeds up is_junction call.

The exact benchmark is system-dependent, here are my numbers (note, that I am on macos and always get False as the result).

Setup:

  • ./configure --with-pydebug && make -j
  • Install pyperf
  • pyperf timeit --setup 'import os; d = os.scandir("."); d1 = next(d); d.close()' 'd1.is_junction()'

With defining_class:

(.venv) ~/Desktop/cpython  main ✔                                                      1 ⚠️
» pyperf timeit --setup 'import os; d = os.scandir("."); d1 = next(d); d.close()' 'd1.is_junction()' 
.....................
Mean +- std dev: 46.1 ns +- 0.5 ns

Without:

(.venv) ~/Desktop/cpython  main ✗                                                         
» pyperf timeit --setup 'import os; d = os.scandir("."); d1 = next(d); d.close()' 'd1.is_junction()'
.....................
Mean +- std dev: 25.0 ns +- 0.3 ns

This happens because is_junction def is changed from METH_METHOD|METH_FASTCALL|METH_KEYWORDS to METH_NOARGS.

I have a PR ready.

Linked PRs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extension-modules C modules in the Modules dir performance Performance or resource usage
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant