PXB-3658: Remove redundant fallocate(PUNCH_HOLE) from local_write_sparse - #1739
Merged
satya-bodapati merged 1 commit intoApr 30, 2026
Merged
Conversation
satya-bodapati
force-pushed
the
PXB-3658-remove-redundant-punch-hole
branch
from
April 17, 2026 12:15
d909311 to
336fd42
Compare
jakub-nowakowski-percona
approved these changes
Apr 30, 2026
satya-bodapati
force-pushed
the
PXB-3658-remove-redundant-punch-hole
branch
from
April 30, 2026 12:27
1257014 to
111dff2
Compare
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
force-pushed
the
PXB-3658-remove-redundant-punch-hole
branch
from
April 30, 2026 12:34
111dff2 to
174e408
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fallocate(PUNCH_HOLE)call fromlocal_write_sparse()inds_local.cc. When writing page-compressed tables,lseekpast unwritten space already produces a sparse hole — the subsequentfallocate(PUNCH_HOLE)is unnecessary for newly created files and adds ~13µs kernel overhead per call.COMPRESSION='zlib'table is ~32% faster (1.48x speedup) with ~1M sparse page entries.suites/compression/pxb_3658_sparse_alloc.shverifies 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/zstdbackup +--decompressrestore: pages are written densely,restore_sparseness()must punch truly-allocated blocksos_file_punch_hole()is neededCOMPRESSION='zlib': no sparse chunks, solocal_write_sparseis never calledFiles 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.shpasses all 5 restore pathsrun.sh -d suites/compression)JIRA: https://perconadev.atlassian.net/browse/PXB-3658
Thank you Xinyu Zhao(@zhaoxinyu) for reporting the issue and suggesting a patch.