(root)/
coreutils-9.4/
src/
ioblksize.h
       1  /* I/O block size definitions for coreutils
       2     Copyright (C) 1989-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Include this file _after_ system headers if possible.  */
      18  
      19  /* sys/stat.h and minmax.h will already have been included by system.h. */
      20  #include "count-leading-zeros.h"
      21  #include "stat-size.h"
      22  
      23  
      24  /* As of May 2014, 128KiB is determined to be the minimum
      25     blksize to best minimize system call overhead.
      26     This can be tested with this script:
      27  
      28     for i in $(seq 0 10); do
      29       bs=$((1024*2**$i))
      30       printf "%7s=" $bs
      31       timeout --foreground -sINT 2 \
      32         dd bs=$bs if=/dev/zero of=/dev/null 2>&1 \
      33           | sed -n 's/.* \([0-9.]* [GM]B\/s\)/\1/p'
      34     done
      35  
      36     With the results shown for these systems:
      37     system #1: 1.7GHz pentium-m with 400MHz DDR2 RAM, arch=i686
      38     system #2: 2.1GHz i3-2310M with 1333MHz DDR3 RAM, arch=x86_64
      39     system #3: 3.2GHz i7-970 with 1333MHz DDR3, arch=x86_64
      40     system #4: 2.20GHz Xeon E5-2660 with 1333MHz DDR3, arch=x86_64
      41     system #5: 2.30GHz i7-3615QM with 1600MHz DDR3, arch=x86_64
      42     system #6: 1.30GHz i5-4250U with 1-channel 1600MHz DDR3, arch=x86_64
      43     system #7: 3.55GHz IBM,8231-E2B with 1066MHz DDR3, POWER7 revision 2.1
      44  
      45                  per-system transfer rate (GB/s)
      46     blksize   #1    #2    #3    #4    #5    #6    #7
      47     ------------------------------------------------------------------------
      48        1024  .73   1.7   2.6   .64   1.0   2.5   1.3
      49        2048  1.3   3.0   4.4   1.2   2.0   4.4   2.5
      50        4096  2.4   5.1   6.5   2.3   3.7   7.4   4.8
      51        8192  3.5   7.3   8.5   4.0   6.0  10.4   9.2
      52       16384  3.9   9.4  10.1   6.3   8.3  13.3  16.8
      53       32768  5.2   9.9  11.1   8.1  10.7  13.2  28.0
      54       65536  5.3  11.2  12.0  10.6  12.8  16.1  41.4
      55      131072  5.5  11.8  12.3  12.1  14.0  16.7  54.8
      56      262144  5.7  11.6  12.5  12.3  14.7  16.4  40.0
      57      524288  5.7  11.4  12.5  12.1  14.7  15.5  34.5
      58     1048576  5.8  11.4  12.6  12.2  14.9  15.7  36.5
      59  
      60  
      61     Note that this is to minimize system call overhead.
      62     Other values may be appropriate to minimize file system
      63     overhead.  For example on my current GNU/Linux system
      64     the readahead setting is 128KiB which was read using:
      65  
      66     file="."
      67     device=$(df --output=source --local "$file" | tail -n1)
      68     echo $(( $(blockdev --getra $device) * 512 ))
      69  
      70     However there isn't a portable way to get the above.
      71     In the future we could use the above method if available
      72     and default to io_blksize() if not.
      73   */
      74  enum { IO_BUFSIZE = 128 * 1024 };
      75  static inline idx_t
      76  io_blksize (struct stat sb)
      77  {
      78    /* Treat impossible blocksizes as if they were IO_BUFSIZE.  */
      79    idx_t blocksize = ST_BLKSIZE (sb) <= 0 ? IO_BUFSIZE : ST_BLKSIZE (sb);
      80  
      81    /* Use a blocksize of at least IO_BUFSIZE bytes, keeping it a
      82       multiple of the original blocksize.  */
      83    blocksize += (IO_BUFSIZE - 1) - (IO_BUFSIZE - 1) % blocksize;
      84  
      85    /* For regular files we can ignore the blocksize if we think we know better.
      86       ZFS sometimes understates the blocksize, because it thinks
      87       apps stupidly allocate a block that large even for small files.
      88       This misinformation can cause coreutils to use wrong-sized blocks.
      89       Work around some of the performance bug by substituting the next
      90       power of two when the reported blocksize is not a power of two.  */
      91    if (S_ISREG (sb.st_mode)
      92        && blocksize & (blocksize - 1))
      93      {
      94        int leading_zeros = count_leading_zeros_ll (blocksize);
      95        if (IDX_MAX < ULLONG_MAX || leading_zeros)
      96          {
      97            unsigned long long power = 1ull << (ULLONG_WIDTH - leading_zeros);
      98            if (power <= IDX_MAX)
      99              blocksize = power;
     100          }
     101      }
     102  
     103    /* Don’t go above the largest power of two that fits in idx_t and size_t,
     104       as that is asking for trouble.  */
     105    return MIN (MIN (IDX_MAX, SIZE_MAX) / 2 + 1,
     106                blocksize);
     107  }