FreeBSD勉強会で「ZFSのスループットはIOサイズが128KB〜256KBあたりで最適になる」という話があったので、
じゃあFSごとにBUFSZを変えられるよういしたらおもしろいかもと
/usr/src/lib/libc/stdio/makebuf.cをみるとst_blksizeがBUFSZになるようなので
カーネコードをみるとちょっまえに入った修正でこんなのがあった。

------------------------------------------------------------------------
r206129 | avg | 2010-04-03 17:39:00 +0900 (Sat, 03 Apr 2010) | 19 lines

vn_stat: take into account va_blocksize when setting st_blksize

As currently st_blksize is always PAGE_SIZE, it is playing safe to not
use any smaller value. For some cases this might not be optimal, but
at least nothing should get broken.

Generally I don't expect this commit to change much for the following
reasons (in case of VREG, VDIR):
- application I/O and physical I/O are sufficiently decoupled by
filesystem code, buffer cache code, cluster and read-ahead logic
- not all applications use st_blksize as a hint, some use f_iosize, some
use fixed block sizes

I expect writes to the middle of files on ZFS to benefit the most from
this change.

Silence from: fs@
MFC after: 2 weeks

------------------------------------------------------------------------

ということで、いまどきのFreeBDS CURRENTだとstat(2)経由でFSの最適IOサイズがわかって全自動でBUFSZが設定される。

ちょっとためしてみた。プログラムはこんなCの初歩:
#include <stdio.h>
int
main()
{
int ch;
while ((ch = getchar()) != EOF)
putchar(ch);
return 0;
}

koie% cc -static copy.c -o copy
#dynlinkだとtrussで余計なものがみえてしまうので.
*** 2kBのファイルを読み込むとread()が5KiBになっている。
koie% dd if=/dev/zero of=chunk.dat bs=2000 count=1
1+0 records in
1+0 records out
2000 bytes transferred in 0.000205 secs (9754195 bytes/sec)
koie% truss ./copy <chunk.dat >/dev/null
__sysctl(0x7fffffffe2a0,0x2,0x7fffffffe2bc,0x7fffffffe2b0,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffe150,0x2,0x7fffffffe180,0x7fffffffe1e8,0x42b300,0xc) = 0 (0x0)
__sysctl(0x7fffffffe180,0x2,0x535f50,0x7fffffffe228,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf","j",1024) = 1 (0x1)
issetugid(0x429d4f,0x7fffffffe2d0,0x6a,0x0,0x2,0x0) = 0 (0x0)
break(0x800000) = 0 (0x0)
__sysctl(0x7fffffffe3c0,0x2,0x7fffffffe3dc,0x7fffffffe3d0,0x0,0x0) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365169664 (0x80052e000)
mmap(0x80092e000,2957312,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34369363968 (0x80092e000)
munmap(0x80052e000,2957312) = 0 (0x0)
sysarch(0x81,0x7fffffffe7d0,0x0,0x0,0x800807040,0x5428a8) = 0 (0x0)
__sysctl(0x7fffffffe7a0,0x2,0x535f80,0x7fffffffe798,0x0,0x0) = 0 (0x0)
fstat(0,{ mode=-rw-r--r-- ,inode=45427,size=2000,blksize=5120 }) = 0 (0x0)
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,5120) = 2000 (0x7d0)
fstat(1,{ mode=crw-rw-rw- ,inode=33,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe6d0) ERR#25 'Inappropriate ioctl for device'
read(0,0x800809000,5120) = 0 (0x0)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,2000) = 2000 (0x7d0)
process exit, rval = 0

*** 5kBのファイルを読み込むとread()が5KiBになっている。
koie% dd if=/dev/zero of=chunk.dat bs=5000 count=1
1+0 records in
1+0 records out
5000 bytes transferred in 0.000184 secs (27165181 bytes/sec)
koie% truss ./copy <chunk.dat >/dev/null
__sysctl(0x7fffffffe2a0,0x2,0x7fffffffe2bc,0x7fffffffe2b0,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffe150,0x2,0x7fffffffe180,0x7fffffffe1e8,0x42b300,0xc) = 0 (0x0)
__sysctl(0x7fffffffe180,0x2,0x535f50,0x7fffffffe228,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf","j",1024) = 1 (0x1)
issetugid(0x429d4f,0x7fffffffe2d0,0x6a,0x0,0x2,0x0) = 0 (0x0)
break(0x800000) = 0 (0x0)
__sysctl(0x7fffffffe3c0,0x2,0x7fffffffe3dc,0x7fffffffe3d0,0x0,0x0) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365169664 (0x80052e000)
mmap(0x80092e000,2957312,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34369363968 (0x80092e000)
munmap(0x80052e000,2957312) = 0 (0x0)
sysarch(0x81,0x7fffffffe7d0,0x0,0x0,0x800807040,0x5428a8) = 0 (0x0)
__sysctl(0x7fffffffe7a0,0x2,0x535f80,0x7fffffffe798,0x0,0x0) = 0 (0x0)
fstat(0,{ mode=-rw-r--r-- ,inode=45427,size=5000,blksize=5120 }) = 0 (0x0)
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,5120) = 5000 (0x1388)
fstat(1,{ mode=crw-rw-rw- ,inode=33,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe6d0) ERR#25 'Inappropriate ioctl for device'
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
read(0,0x800809000,5120) = 0 (0x0)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,904) = 904 (0x388)
process exit, rval = 0

*** 10kBのファイルを読み込むとread()が10KiBになっている。
koie% dd if=/dev/zero of=chunk.dat bs=10000 count=1
1+0 records in
1+0 records out
10000 bytes transferred in 0.000228 secs (43827628 bytes/sec)
koie% truss ./copy <chunk.dat >/dev/null
__sysctl(0x7fffffffe2a0,0x2,0x7fffffffe2bc,0x7fffffffe2b0,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffe150,0x2,0x7fffffffe180,0x7fffffffe1e8,0x42b300,0xc) = 0 (0x0)
__sysctl(0x7fffffffe180,0x2,0x535f50,0x7fffffffe228,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf","j",1024) = 1 (0x1)
issetugid(0x429d4f,0x7fffffffe2d0,0x6a,0x0,0x2,0x0) = 0 (0x0)
break(0x800000) = 0 (0x0)
__sysctl(0x7fffffffe3c0,0x2,0x7fffffffe3dc,0x7fffffffe3d0,0x0,0x0) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365169664 (0x80052e000)
mmap(0x80092e000,2957312,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34369363968 (0x80092e000)
munmap(0x80052e000,2957312) = 0 (0x0)
sysarch(0x81,0x7fffffffe7d0,0x0,0x0,0x800807040,0x5428a8) = 0 (0x0)
__sysctl(0x7fffffffe7a0,0x2,0x535f80,0x7fffffffe798,0x0,0x0) = 0 (0x0)
fstat(0,{ mode=-rw-r--r-- ,inode=45427,size=10000,blksize=10240 }) = 0 (0x0)
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,10240) = 10000 (0x2710)
fstat(1,{ mode=crw-rw-rw- ,inode=33,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe6d0) ERR#25 'Inappropriate ioctl for device'
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
read(0,0x80080a800,10240) = 0 (0x0)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,1808) = 1808 (0x710)
process exit, rval = 0

*** 100kBのファイルを読み込むとread()が100352B(0x18800)になっている。
koie% dd if=/dev/zero of=chunk.dat bs=100000 count=1
1+0 records in
1+0 records out
100000 bytes transferred in 0.000609 secs (164224902 bytes/sec)
koie% truss ./copy <chunk.dat >/dev/null
__sysctl(0x7fffffffe2a0,0x2,0x7fffffffe2bc,0x7fffffffe2b0,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffe150,0x2,0x7fffffffe180,0x7fffffffe1e8,0x42b300,0xc) = 0 (0x0)
__sysctl(0x7fffffffe180,0x2,0x535f50,0x7fffffffe228,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf","j",1024) = 1 (0x1)
issetugid(0x429d4f,0x7fffffffe2d0,0x6a,0x0,0x2,0x0) = 0 (0x0)
break(0x800000) = 0 (0x0)
__sysctl(0x7fffffffe3c0,0x2,0x7fffffffe3dc,0x7fffffffe3d0,0x0,0x0) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365169664 (0x80052e000)
mmap(0x80092e000,2957312,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34369363968 (0x80092e000)
munmap(0x80052e000,2957312) = 0 (0x0)
sysarch(0x81,0x7fffffffe7d0,0x0,0x0,0x800807040,0x5428a8) = 0 (0x0)
__sysctl(0x7fffffffe7a0,0x2,0x535f80,0x7fffffffe798,0x0,0x0) = 0 (0x0)
fstat(0,{ mode=-rw-r--r-- ,inode=45427,size=100000,blksize=100352 }) = 0 (0x0)
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,100352) = 100000 (0x186a0)
fstat(1,{ mode=crw-rw-rw- ,inode=33,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe6d0) ERR#25 'Inappropriate ioctl for device'
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※13回くりかえし
read(0,0x800808000,100352) = 0 (0x0)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,1696) = 1696 (0x6a0)
process exit, rval = 0

*** 1MBのファイルを読み込むとread()が128KiBになっている。
koie% dd if=/dev/zero of=chunk.dat bs=1000000 count=1
1+0 records in
1+0 records out
1000000 bytes transferred in 0.005239 secs (190875762 bytes/sec)
koie% truss ./copy <chunk.dat >/dev/null
__sysctl(0x7fffffffe2a0,0x2,0x7fffffffe2bc,0x7fffffffe2b0,0x0,0x0) = 0 (0x0)
__sysctl(0x7fffffffe150,0x2,0x7fffffffe180,0x7fffffffe1e8,0x42b300,0xc) = 0 (0x0)
__sysctl(0x7fffffffe180,0x2,0x535f50,0x7fffffffe228,0x0,0x0) = 0 (0x0)
readlink("/etc/malloc.conf","j",1024) = 1 (0x1)
issetugid(0x429d4f,0x7fffffffe2d0,0x6a,0x0,0x2,0x0) = 0 (0x0)
break(0x800000) = 0 (0x0)
__sysctl(0x7fffffffe3c0,0x2,0x7fffffffe3dc,0x7fffffffe3d0,0x0,0x0) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34365169664 (0x80052e000)
mmap(0x80092e000,2957312,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34369363968 (0x80092e000)
munmap(0x80052e000,2957312) = 0 (0x0)
sysarch(0x81,0x7fffffffe7d0,0x0,0x0,0x800807040,0x5428a8) = 0 (0x0)
__sysctl(0x7fffffffe7a0,0x2,0x535f80,0x7fffffffe798,0x0,0x0) = 0 (0x0)
fstat(0,{ mode=-rw-r--r-- ,inode=45427,size=1000000,blksize=131072 }) = 0 (0x0)
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
fstat(1,{ mode=crw-rw-rw- ,inode=33,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe6d0) ERR#25 'Inappropriate ioctl for device'
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 131072 (0x20000)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,131072) = 82496 (0x14240)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,4096) = 4096 (0x1000)
※くりかえし
read(0,0x800808000,131072) = 0 (0x0)
write(1,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,576) = 576 (0x240)
process exit, rval = 0
koie%