Skip to content

pathlib's deferred joining slows real workloads #113888

Closed as not planned
Closed as not planned

Description

@barneygale

In #104996 I made pathlib defer joining of arguments given to path initialisers (like PurePath('a', 'b') and via joinpath(), __truediv__() and __rtruediv__().

This "optimisation" often results in more path joining. Consider:

test_path = pathlib.Path('/home', 'barney', 'projects', 'cpython', 'Lib', 'test')
print(test_path / 'test_abc.py')
print(test_path / 'test_pathlib')
print(test_path / 'test_zipfile')

(the print() could be any operation on the path object other than a further join)

Under the hood this results in the following calls:

os.path.join('/home', 'barney', 'projects', 'cpython', 'Lib', 'test', 'test_abc.py')  # cost=7
os.path.join('/home', 'barney', 'projects', 'cpython', 'Lib', 'test', 'test_pathlib')  # cost=7
os.path.join('/home', 'barney', 'projects', 'cpython', 'Lib', 'test', 'test_zipfile')  # cost=7
# total cost: 21

If we'd naively joined the paths, we'd instead have:

os.path.join('/home', 'barney', 'projects', 'cpython', 'Lib', 'test')  # cost=6
os.path.join('/home/barney/projects/cpython/Lib/test', 'test_abc.py')  # cost=2
os.path.join('/home/barney/projects/cpython/Lib/test', 'test_pathlib')  # cost=2
os.path.join('/home/barney/projects/cpython/Lib/test', 'test_zipfile')  # cost=2
# total cost: 12

Activity

  1. added a commit that references this issue on Jan 10, 2024
  2. barneygale commented on Jan 13, 2024

    @barneygale
    ContributorAuthor

    OTOH:

    print(pathlib.Path('/home') / 'barney' / 'projects' / 'cpython' / 'Lib' / 'test')

    With the current implementation this causes:

    os.path.join('/home', 'barney', 'projects', 'cpython', 'Lib', 'test')  # cost=6
    # total cost: 6

    But if we joined up-front, it would cause:

    os.path.join('/home', 'barney') # cost=2
    os.path.join('/home/barney', 'projects') # cost=2
    os.path.join('/home/barney/projects', 'cpython') # cost=2
    os.path.join('/home/barney/projects/cpython', 'Lib') # cost=2
    os.path.join('/home/barney/projects/cpython/Lib', 'test') # cost=2
    # total cost: 10
  3. barneygale commented on Jan 13, 2024

    @barneygale
    ContributorAuthor

    I haven't been able to establish which is better, so I'll close this issue as not planned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions