Skip to content

Use high-performance os.sendfile() in shutil.copy* #77820

Closed

Description

@giampaolo
BPO 33639
Nosy @facundobatista, @ncoghlan, @vstinner, @giampaolo, @bitdancer, @encukou, @vadmium, @desbma
PRs
  • bpo-33639: use high-performance os.sendfile() in shutil.copy* #7100
  • Superseder
  • bpo-33671: Efficient zero-copy for shutil.copy* functions (Linux, OSX and Win)
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2018-05-28.16:28:30.230>
    created_at = <Date 2018-05-24.20:15:29.809>
    labels = ['3.8', 'library', 'performance']
    title = 'Use high-performance os.sendfile() in shutil.copy*'
    updated_at = <Date 2018-05-28.16:29:08.167>
    user = 'https://github.com/giampaolo'

    bugs.python.org fields:

    activity = <Date 2018-05-28.16:29:08.167>
    actor = 'giampaolo.rodola'
    assignee = 'none'
    closed = True
    closed_date = <Date 2018-05-28.16:28:30.230>
    closer = 'giampaolo.rodola'
    components = ['Library (Lib)']
    creation = <Date 2018-05-24.20:15:29.809>
    creator = 'giampaolo.rodola'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 33639
    keywords = ['patch']
    message_count = 8.0
    messages = ['317611', '317622', '317627', '317630', '317634', '317738', '317882', '317883']
    nosy_count = 11.0
    nosy_names = ['facundobatista', 'ncoghlan', 'vstinner', 'giampaolo.rodola', 'StyXman', 'r.david.murray', 'petr.viktorin', 'neologix', 'python-dev', 'martin.panter', 'desbma']
    pr_nums = ['7100']
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'patch review'
    status = 'closed'
    superseder = '33671'
    type = 'performance'
    url = 'https://bugs.python.org/issue33639'
    versions = ['Python 3.8']

    Activity

    1. giampaolo commented on May 24, 2018

      @giampaolo
      ContributorAuthor

      This is a follow up of bpo-25063 and similar to socket.sendfile() (bpo-17552). It provides a 20/25% speedup when copying files with shutil.copyfile(), shutil.copy() and shutil.copy2(). Differently from bpo-25063 this is used for filesystem files only and copyfileobj() is left alone.

      Unmerged bpo-26826 is also related to this. I applied bpo-26826 patch and built a wrapper around copy_file_range() and the speedup is basically the same. Nevertheless, even when bpo-26826 gets merged it probably makes sense to rely on sendfile() in case copy_file_range() is not available (it was introduced in 2016) or the UNIX platform supports file-to-file copy via sendfile(2) (even though I'm not aware of any, so this would basically be Linux-only).

      Some benchmarks:

          $ dd if=/dev/urandom of=/tmp/f1 bs=1K count=128
          $ time ./python -m timeit -s 'import shutil; p1 = "/tmp/f1"; p2 = "/tmp/f2"' 'shutil.copyfile(p1, p2)'

      128K copy
      =========

      --- without patch:

      2000 loops, best of 5: 160 usec per loop
      
      real    0m2.353s
      user    0m0.454s
      sys     0m1.435s
      

      --- with patch:

      2000 loops, best of 5: 187 usec per loop
      
      real    0m2.724s
      user    0m0.627s
      sys     0m1.634s
      

      8MB copy
      ========

      $ dd if=/dev/urandom of=/tmp/f1 bs=1M count=8

      --- without patch:

      50 loops, best of 5: 9.51 msec per loop
      
      real    0m3.392s
      user    0m0.343s
      sys     0m2.478s
      

      --- with patch:

      50 loops, best of 5: 7.75 msec per loop
      
      real    0m2.878s
      user    0m0.105s
      sys     0m2.187s
      

      512MB copy
      ==========

      --- without patch:

      1 loop, best of 5: 872 msec per loop
      
      real    0m5.574s
      user    0m0.402s
      sys     0m3.115s
      

      --- with patch:

      1 loop, best of 5: 646 msec per loop
      
      real    0m5.475s
      user    0m0.037s
      sys     0m2.959s
      
    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      performancePerformance or resource usage
      on May 24, 2018
    3. desbma commented on May 24, 2018

      desbmamannequin
      Mannequin
    4. giampaolo commented on May 24, 2018

      @giampaolo
      ContributorAuthor

      Oh! I got confused by the fact that bpo-25063 was rejected due to concerns about copyfileobj() otherwise I would have commented on your patch which I totally missed. Yes, this overlaps with bpo-25156 patch but it uses the same logic of socket.sendfile() which IMO is more robust. If you agree I'd close bpo-25156 and continue in here, and I'm more than happy to co-author the contribution if that's OK with you.

    5. desbma commented on May 24, 2018

      desbmamannequin
      Mannequin

      Honestly, whatever gets this thing moving forward is good with me.

      I'm a bit depressed by the number of issues here that have a good patch waiting to be merged, or even read, and that languish for years.

      I haven't read your patch in detail, but if others agree that it is better than mine and can be merged, let's do it.

    6. vstinner commented on May 24, 2018

      @vstinner
      Member

      I'm a bit depressed by the number of issues here that have a good patch waiting to be merged, or even read, and that languish for years.

      I'm really sorry about that. We, core developers, are doing our best, but we are 34 active core developers who merged 5000 pull requests in 1 year. We don't scale well :-(

      We are working on getting more people onboard.

    7. giampaolo commented on May 26, 2018

      @giampaolo
      ContributorAuthor

      I updated the code to rely on sendfile(2) on Linux only, which apparently is the only one supporting copy between regular files and added a check to fail immediately in case the filesystem is full.

      Can somebody review the patch?

    8. giampaolo commented on May 28, 2018

      @giampaolo
      ContributorAuthor

      Closing as duplicate of bpo-33671.

    9. giampaolo commented on May 28, 2018

      @giampaolo
      ContributorAuthor

      Closing as duplicate of bpo-33671.

    10. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.8 (EOL)end of lifeperformancePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directory

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions