Skip to content

PXB-3658: Remove redundant fallocate(PUNCH_HOLE) from local_write_sparse - #1739

Merged
satya-bodapati merged 1 commit into
percona:8.0from
satya-bodapati:PXB-3658-remove-redundant-punch-hole
Apr 30, 2026
Merged

PXB-3658: Remove redundant fallocate(PUNCH_HOLE) from local_write_sparse#1739
satya-bodapati merged 1 commit into
percona:8.0from
satya-bodapati:PXB-3658-remove-redundant-punch-hole

Conversation

@satya-bodapati

@satya-bodapati satya-bodapati commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Remove the redundant fallocate(PUNCH_HOLE) call from local_write_sparse() in ds_local.cc. When writing page-compressed tables, lseek past unwritten space already produces a sparse hole — the subsequent fallocate(PUNCH_HOLE) is unnecessary for newly created files and adds ~13µs kernel overhead per call.
  • Benchmark result: xbstream restore of a 10GB COMPRESSION='zlib' table is ~32% faster (1.48x speedup) with ~1M sparse page entries.
  • New test: suites/compression/pxb_3658_sparse_alloc.sh verifies allocated disk sizes remain correct across 5 restore paths (local, xbstream, xbstream+lz4, local+zstd+decompress, stream+zstd+decompress).

Details

Scenarios where this fix helps

  • xtrabackup --backup --target-dir (local backup of compressed tables)
  • xtrabackup --copy-back (restoring compressed tables from backup)
  • xbstream -x (extracting compressed tables from stream)

Scenarios where this fix does NOT help

  • --compress=lz4/zstd backup + --decompress restore: pages are written densely, restore_sparseness() must punch truly-allocated blocks
  • Incremental delta apply: destination file already exists with allocated blocks, os_file_punch_hole() is needed
  • Tables without COMPRESSION='zlib': no sparse chunks, so local_write_sparse is never called

Files changed

  • storage/innobase/xtrabackup/src/ds_local.cc — removed 9 lines (fallocate block + supporting variables)
  • storage/innobase/xtrabackup/test/suites/compression/pxb_3658_sparse_alloc.sh — new integration test (328 lines)

Test plan

  • suites/compression/pxb_3658_sparse_alloc.sh passes all 5 restore paths
  • Existing compression test suite passes (run.sh -d suites/compression)
  • Verify sparse file sizes match original after each restore path

JIRA: https://perconadev.atlassian.net/browse/PXB-3658

Thank you Xinyu Zhao(@zhaoxinyu) for reporting the issue and suggesting a patch.

@satya-bodapati
satya-bodapati force-pushed the PXB-3658-remove-redundant-punch-hole branch from 1257014 to 111dff2 Compare April 30, 2026 12:27
JIRA: https://perconadev.atlassian.net/browse/PXB-3658

Problem:
When writing page-compressed tables, local_write_sparse() calls
fallocate(PUNCH_HOLE) on gaps that were already created as sparse
holes via lseek. This is redundant for newly created files -- lseek
past unwritten space already produces a sparse hole with no allocated
blocks. Each redundant fallocate call costs ~13us of kernel overhead.

Benchmark (10GB COMPRESSION='zlib' table, ~1M sparse page entries):
  - xbstream restore: ~32% faster (1.48x speedup)
  - Identical file sizes (apparent and allocated) with and without patch

Fix:
Remove the fallocate(PUNCH_HOLE) block, and the my_tell()/seek
variable that only existed to support it, from local_write_sparse
in ds_local.cc.

local_write_sparse() lacked a posix_fadvise(DONTNEED) call, unlike
local_write() which already has one. Without it, page-compressed
table restores can accumulate dirty pages in the page cache. Add
the same fadvise hint at the end of local_write_sparse() to allow
the kernel to evict written pages and reduce memory pressure during
large restores.

Scenarios where this fix helps:
  - xtrabackup --backup --target-dir (local backup of compressed tables)
  - xtrabackup --copy-back (restoring compressed tables from backup)
  - xbstream -x (extracting compressed tables from stream)

Scenarios where this fix does NOT help:
  - --compress=lz4/zstd backup + --decompress restore: pages are written
    densely, restore_sparseness() must punch truly-allocated blocks
  - Incremental delta apply: destination file already exists with
    allocated blocks, os_file_punch_hole() is needed
  - Tables without COMPRESSION='zlib': no sparse chunks, so
    local_write_sparse is never called

Test: storage/innobase/xtrabackup/test/suites/compression/pxb_3658_sparse_alloc.sh

Thank you Xinyu Zhao for reporting the issue and suggesting a patch.
@satya-bodapati
satya-bodapati force-pushed the PXB-3658-remove-redundant-punch-hole branch from 111dff2 to 174e408 Compare April 30, 2026 12:34
@satya-bodapati
satya-bodapati merged commit f113c28 into percona:8.0 Apr 30, 2026
3 checks passed
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 this pull request may close these issues.

2 participants