Commit e895791
committed
dd: write complete blocks without buffering them first
BufferedOutput::write_blocks copies the incoming bytes into its internal
buffer, hands that buffer to the inner writer, clears it, and then
re-buffers the trailing partial block -- even when nothing was pending
and the incoming bytes already form complete blocks. That is the common
case: the copy loop hands over a multiple of the output block size on
every iteration, so each one paid for a full memcpy of the block.
Take that case directly: with an empty internal buffer, write the
complete blocks straight from the caller's slice and buffer only the
remainder. The existing path still handles a pending partial block.
Instruction counts (cachegrind, same toolchain and base):
dd_copy_separate_blocks 55,916,646 -> 5,447,251 -90.26%
dd_copy_default 36,615,676 -> 30,718,154 -16.11%
dd_copy_with_seek 8,511,906 -> 8,488,175 -0.28%
dd_copy_with_skip 8,412,120 -> 8,389,437 -0.27%
dd_copy_4k_blocks 4,742,612 -> 4,730,524 -0.25%
dd_copy_8k_blocks 4,408,987 -> 4,401,037 -0.18%
dd_copy_partial 3,222,128 -> 3,220,704 -0.04%
dd_copy_64k_blocks 5,107,029 -> 5,105,557 -0.03%
dd_copy_1m_blocks 9,410,822 -> 9,410,932 +0.00%
Peak heap is unchanged (DHAT, 236,549 -> 236,546 bytes).1 parent 50b8ead commit e895791
1 file changed
Lines changed: 22 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
71 | 92 | | |
72 | 93 | | |
73 | 94 | | |
74 | 95 | | |
75 | 96 | | |
76 | 97 | | |
77 | | - | |
| 98 | + | |
78 | 99 | | |
79 | 100 | | |
80 | 101 | | |
| |||
0 commit comments