How does RECORDLENGTH affect your exp speed?

exp导出工具的几个常用参数想必大家都很熟悉;有时为了加速导出作业我们会加上direct=y,进一步的可能就会设置RECORDLENGTH参数了,Oracle官方对这个参数的定义是:length of IO record;这个解释过于简单了,偶有余暇来探究一下RECORDLENGTH的工作原理:

[maclean@rh2 test]$ exp help=y

Export: Release 10.2.0.4.0 - Production on Mon Nov 8 17:26:34 2010
Copyright (c) 1982, 2007, Oracle.  All rights reserved.
You can let Export prompt you for parameters by entering the EXP
command followed by your username/password:

     Example: EXP SCOTT/TIGER

Or, you can control how Export runs by entering the EXP command followed
by various arguments. To specify parameters, you use keywords:

     Format:  EXP KEYWORD=value or KEYWORD=(value1,value2,...,valueN)
     Example: EXP SCOTT/TIGER GRANTS=Y TABLES=(EMP,DEPT,MGR)
               or TABLES=(T1:P1,T1:P2), if T1 is partitioned table

USERID must be the first parameter on the command line.

Keyword    Description (Default)      Keyword      Description (Default)
--------------------------------------------------------------------------
USERID     username/password          FULL         export entire file (N)
BUFFER     size of data buffer        OWNER        list of owner usernames
FILE       output files (EXPDAT.DMP)  TABLES       list of table names
COMPRESS   import into one extent (Y) RECORDLENGTH length of IO record
GRANTS     export grants (Y)          INCTYPE      incremental export type
INDEXES    export indexes (Y)         RECORD       track incr. export (Y)
DIRECT     direct path (N)            TRIGGERS     export triggers (Y)
LOG        log file of screen output  STATISTICS   analyze objects (ESTIMATE)
ROWS       export data rows (Y)       PARFILE      parameter filename
CONSISTENT cross-table consistency(N) CONSTRAINTS  export constraints (Y)

OBJECT_CONSISTENT    transaction set to read only during object export (N)
FEEDBACK             display progress every x rows (0)
FILESIZE             maximum size of each dump file
FLASHBACK_SCN        SCN used to set session snapshot back to
FLASHBACK_TIME       time used to get the SCN closest to the specified time
QUERY                select clause used to export a subset of a table
RESUMABLE            suspend when a space related error is encountered(N)
RESUMABLE_NAME       text string used to identify resumable statement
RESUMABLE_TIMEOUT    wait time for RESUMABLE
TTS_FULL_CHECK       perform full or partial dependency check for TTS
VOLSIZE              number of bytes to write to each tape volume
TABLESPACES          list of tablespaces to export
TRANSPORT_TABLESPACE export transportable tablespace metadata (N)
TEMPLATE             template name which invokes iAS mode export

Export terminated successfully without warnings.

/* 针对使用direct=y直接路径,未使用recordlength的作业进行strace系统调用追踪 */

[maclean@rh2 test]$ strace -o exp1.trace exp maclean/maclean file=tv.dmp tables=tv direct=y

Export: Release 10.2.0.4.0 - Production on Mon Nov 8 17:27:23 2010
Copyright (c) 1982, 2007, Oracle.  All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Export done in US7ASCII character set and UTF8 NCHAR character set
server uses ZHS16GBK character set (possible charset conversion)

About to export specified tables via Direct Path ...
. . exporting table                             TV    6602624 rows exported
Export terminated successfully without warnings.

[maclean@rh2 test]$ ps -ef|grep exp
maclean  12265 12198 55 17:27 pts/2    00:00:02 strace -o exp1.trace exp maclean/maclean file=tv.dmp tables=tv direct=y
maclean  12266 12265 24 17:27 pts/2    00:00:01 exp                 file=tv.dmp tables=tv direct=y
maclean  12269 12233  0 17:27 pts/3    00:00:00 grep exp
[maclean@rh2 test]$ pmap -x 12266
12266:   exp                 file=tv.dmp tables=tv direct=y
Address           Kbytes     RSS   Dirty Mode   Mapping
0000000000400000     608     280       0 r-x--  exp
0000000000698000      16      16       8 rwx--  exp
000000000069c000      40      40      40 rwx--    [ anon ]
000000000f330000     876     656     656 rwx--    [ anon ]
00000039f1800000     112     100       0 r-x--  ld-2.5.so
00000039f1a1b000       4       4       4 r-x--  ld-2.5.so
00000039f1a1c000       4       4       4 rwx--  ld-2.5.so
00000039f1c00000    1336     452       0 r-x--  libc-2.5.so
00000039f1d4e000    2044       0       0 -----  libc-2.5.so
00000039f1f4d000      16      16       8 r-x--  libc-2.5.so
00000039f1f51000       4       4       4 rwx--  libc-2.5.so
00000039f1f52000      20      20      20 rwx--    [ anon ]
00000039f2000000     520      20       0 r-x--  libm-2.5.so
00000039f2082000    2044       0       0 -----  libm-2.5.so
00000039f2281000       4       4       4 r-x--  libm-2.5.so
00000039f2282000       4       4       4 rwx--  libm-2.5.so
00000039f2400000       8       8       0 r-x--  libdl-2.5.so
00000039f2402000    2048       0       0 -----  libdl-2.5.so
00000039f2602000       4       4       4 r-x--  libdl-2.5.so
00000039f2603000       4       4       4 rwx--  libdl-2.5.so
00000039f2800000      88      60       0 r-x--  libpthread-2.5.so
00000039f2816000    2044       0       0 -----  libpthread-2.5.so
00000039f2a15000       4       4       4 r-x--  libpthread-2.5.so
00000039f2a16000       4       4       4 rwx--  libpthread-2.5.so
00000039f2a17000      16       4       4 rwx--    [ anon ]
00000039f5c00000      84      24       0 r-x--  libnsl-2.5.so
00000039f5c15000    2044       0       0 -----  libnsl-2.5.so
00000039f5e14000       4       4       4 r-x--  libnsl-2.5.so
00000039f5e15000       4       4       4 rwx--  libnsl-2.5.so
00000039f5e16000       8       0       0 rwx--    [ anon ]
00002b6ebde28000       8       8       8 rwx--    [ anon ]
00002b6ebde2a000   18632    5024       4 r-x--  libclntsh.so.10.1
00002b6ebf05c000    2044       0       0 -----  libclntsh.so.10.1
00002b6ebf25b000     656     656     640 rwx--  libclntsh.so.10.1
00002b6ebf2ff000     112      32      32 rwx--    [ anon ]
00002b6ebf31b000    3004    1280     416 r-x--  libnnz10.so
00002b6ebf60a000    1020       0       0 -----  libnnz10.so
00002b6ebf709000     708     256     256 rwx--  libnnz10.so
00002b6ebf7ba000       4       4       4 rwx--    [ anon ]
00002b6ebf7d8000     432     164     164 rwx--    [ anon ]
00002b6ebf844000     400       8       0 r-x--  timezlrg.dat
00002b6ebf8c5000      40      28       0 r-x--  libnss_files-2.5.so
00002b6ebf8cf000    2044       0       0 -----  libnss_files-2.5.so
00002b6ebface000       4       4       4 r-x--  libnss_files-2.5.so
00002b6ebfacf000       4       4       4 rwx--  libnss_files-2.5.so
00002b6ebfad0000       4       4       4 rwx--    [ anon ]
00007ffff2cb3000      84      64      64 rwx--    [ stack ]
ffffffffff600000    8192       0       0 -----    [ anon ]
----------------  ------  ------  ------
total kB           51408    9276    2380
[maclean@rh2 test]$ cd /proc/12266/fd
[maclean@rh2 fd]$ ls -l
总计 0
lrwx------ 1 maclean oinstall 64 11-08 17:27 0 -> /dev/pts/2
lrwx------ 1 maclean oinstall 64 11-08 17:27 1 -> /dev/pts/2
lrwx------ 1 maclean oinstall 64 11-08 17:27 2 -> /dev/pts/2
lr-x------ 1 maclean oinstall 64 11-08 17:27 3 -> /s01/10gdb/rdbms/mesg/expus.msb
lr-x------ 1 maclean oinstall 64 11-08 17:27 4 -> /s01/10gdb/oracore/mesg/lrmus.msb
lr-x------ 1 maclean oinstall 64 11-08 17:27 5 -> /s01/10gdb/rdbms/mesg/ocius.msb
lrwx------ 1 maclean oinstall 64 11-08 17:27 6 -> socket:[56016]
l-wx------ 1 maclean oinstall 64 11-08 17:27 7 -> /home/maclean/test/tv.dmp
l-wx------ 1 maclean oinstall 64 11-08 17:27 8 -> pipe:[56017]
lr-x------ 1 maclean oinstall 64 11-08 17:27 9 -> pipe:[56018]

/* 同时分析该exp进程的地址空间及打开文件描述符,可以看到这里的fd=>7指向了导出文件tv.dmp */

节选trace部分内容:
read(9, "\7\333\0\0\6\0\0\0\0\0\10\0 \0\0009:57\5\0VALID\1\0N\1\0N"..., 2064) = 2064
read(9, "2008-03-12:00:39:58\5\0VALID\1\0N\1\0N"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0LID\1\0N\1\0N\1\0N\3\0SYS\v\0I_S"..., 2064) = 2064
read(9, "\376\377\3\0\302\5$\3\0\302\5$\5\0INDEX\7\0xl\3\f\1(<\7\0xl"..., 1958) = 1958
read(9, "\0\327\0\0\6\0\0\0\0\00059\5\0VALID\1\0N\1\0N\1\0N\5\0OU"..., 2064) = 215
write(7, "9:57\5\0VALID\1\0N\1\0N\1\0N\3\0SYS\t\0ATEMP"..., 4096) = 4096
write(7, "\0N\1\0N\3\0SYS\v\0I_SUMDEP$_2\376\377\3\0\302\5\17\3\0"..., 4096) = 4096
write(8, "\0r\0\0\6\0\0\0\0\0\3[\235@\177\202\277n+\0\0\0 \0\0\0\0\0\0\200a\314"..., 114) = 114
read(9, "\7\333\0\0\6\0\0\0\0\0\10\0 \0\0ALID\1\0N\1\0N\1\0N\5\0OU"..., 2064) = 2064
read(9, "\0N\1\0N\1\0N\3\0SYS\t\0MON_MODS$\376\377\3\0\302\5T\3"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\1)\1\7\0xl\3\f\1)\1\23\0002008-03-"..., 2064) = 2064
read(9, "ABLE\7\0xl\3\f\1)\26\7\0xl\3\f\1)\26\23\0002008-03-"..., 1958) = 1958
read(9, "\0\327\0\0\6\0\0\0\0\0\302\0061\3\0\302\0061\5\0INDEX\7\0xl\3\f\1"..., 2064) = 215
write(7, "ALID\1\0N\1\0N\1\0N\5\0OUTLN\17\0OL$NODE_OL"..., 4096) = 4096
write(7, ")\1\7\0xl\3\f\1)\1\23\0002008-03-12:00:40:00"..., 4096) = 4096
write(8, "\0r\0\0\6\0\0\0\0\0\3[\236@\177\202\277n+\0\0\0 \0\0\0\0\0\0\200a\314"..., 114) = 114 

/* 文件描述符为9的是一个管道文件,不难猜测其数据来源于TV表所在数据文件;
   fd为8的因该是system call的输出管道,可以不用关心  */ 

[maclean@rh2 test]$ strace -o exp2.trace exp maclean/maclean file=tv.dmp tables=tv direct=y recordlength=32768

Export: Release 10.2.0.4.0 - Production on Mon Nov 8 18:31:07 2010

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Export done in US7ASCII character set and UTF8 NCHAR character set
server uses ZHS16GBK character set (possible charset conversion)

About to export specified tables via Direct Path ...
. . exporting table                             TV    6602624 rows exported
Export terminated successfully without warnings.

节选的recordlength为32k时的system call trace:

read(9, "\7\333\0\0\6\0\0\0\0\0\10\0\200\0\0ONYM\7\0xl\3\f\2\t9\7\0xl"..., 2064) = 2064
read(9, "\5\0VALID\1\0N\1\0N\1\0N\7\0OLAPSYS\10\0CWM$U"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0002:01:09:00\5\0VALID\1\0N\1\0"..., 2064) = 2064
read(9, "\0N\7\0OLAPSYS\26\0CWM2$AWDIMCREATEACC"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\0\303\5T\2\5\0TABLE\7\0xl\3\f\2\n\4\7"..., 2064) = 2064
read(9, "\5T\25\4\0\303\5T\25\5\0INDEX\7\0xl\3\f\2\n\5\7\0xl\3\f\2"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\4\0\303\5T'\5\0INDEX\7\0xl\3\f\2\n\5"..., 2064) = 2064
read(9, "ID\1\0N\1\0N\1\0N\7\0OLAPSYS\23\0CWM2$HIERA"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0007:32\5\0VALID\1\0N\1\0N\1\0N\7\0"..., 2064) = 2064
read(9, "-10-20:20:07:33\5\0VALID\1\0N\1\0N\1\0N\7"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\0VALID\1\0N\1\0N\1\0N\7\0OLAPS"..., 2064) = 2064
read(9, "\0CWM2_OLAP_MEASURE\376\377\4\0\303\5U\"\376\377\7\0PA"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\0N\1\0N\1\0N\6\0PUBLIC\23\0CWM2"..., 2064) = 2064
read(9, "008-03-12:01:09:11\5\0VALID\1\0N\1\0N\1"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\0N\7\0OLAPSYS\35\0ALL$OLAP2"..., 2064) = 2064
read(9, "TTR_USES\376\377\4\0\303\5V\v\376\377\4\0VIEW\7\0xl\3\f\2\n"..., 1958) = 1958
read(9, "\3\v\0\0\6\0\0\0\0\0\2\n\23\7\0xn\n\24\25\10'\23\0002008-03-"..., 2064) = 779
write(7, "ONYM\7\0xl\3\f\2\t9\7\0xl\3\f\2\t9\23\0002008-03-"..., 4096) = 4096
write(7, "008-03-12:01:09:02\5\0VALID\1\0N\1\0N\1"..., 28672) = 28672

/* 以上可以看到exp进程首先了累计(accumulates)读取了32k左右的数据到缓存中,之后以2个write调用分别写出4096和28672 bytes
    的数据,也就是在读取32k数据后全部写出再依次循环,不同于上面的累计读取8k然后写出8k
*/

/* 对比pmap报告可以发现内存使用也发生了变化 */

00002b9f6e034000     708     256     256 rwx--  libnnz10.so
00002b9f6e0e5000       4       4       4 rwx--    [ anon ]
00002b9f6e103000     432     212     212 rwx--    [ anon ]
00002b9f6e16f000     400       8       0 r-x--  timezlrg.dat
00002b9f6e1f0000      40      28       0 r-x--  libnss_files-2.5.so

/* 相对应的是exp进程的匿名块anon(00002b9f6e103000     432     212     212 rwx--    [ anon ])部分rss和Dirty,
    由原来的164k增长到了212k,增长了48k
*/

[maclean@rh2 test]$ strace -o exp3.trace exp maclean/maclean file=tv.dmp tables=tv direct=y recordlength=65535

Export: Release 10.2.0.4.0 - Production on Mon Nov 8 17:53:25 2010
Copyright (c) 1982, 2007, Oracle.  All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Export done in US7ASCII character set and UTF8 NCHAR character set
server uses ZHS16GBK character set (possible charset conversion)

About to export specified tables via Direct Path ...
. . exporting table                             TV    6602624 rows exported
Export terminated successfully without warnings.

/* 以65535 recordlength导出的strace 记录 */

read(9, "\7\333\0\0\6\0\0\0\0\0\10\377\377\0\0MADMIN\21\0SYS_IOT_T"..., 2064) = 2011
read(9, "\7\333\0\0\6\0\0\0\0\00010-09-29:18:14:08\5\0VAL"..., 2064) = 2064
read(9, "4:09\5\0VALID\1\0N\1\0N\1\0N\3\0SYS\23\0AQ$AQ"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\4\0\303\6 b\5\0INDEX\7\0xn\t\36\17!0"..., 2064) = 2064
read(9, ":21\5\0VALID\1\0N\1\0N\1\0N\3\0SYS\4\0HR11\376\377"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0J$\4\0P101\4\0\303\6!>\4\0\303\6\"9\17\0"..., 2064) = 2064
read(9, "P101\4\0\303\6!O\4\0\303\6\">\17\0INDEX PARTITIO"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0I1CCOL$\4\0P101\4\0\303\6!a\4\0\303"..., 2064) = 2064
read(9, ":44\5\0VALID\1\0N\1\0N\1\0N\3\0SYS\16\0WRH$_P"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0N_HISTORY_PK\31\0WRH$_ACT"..., 2064) = 2064
read(9, "SQLSTAT_PK\31\0WRH$_SQLSTA_14284528"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\0002010-10-18:20:48:28\5\0"..., 2064) = 2064
read(9, ";\f\23\0002010-10-20:19:58:11\5\0VALID\1\0"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0RT$\376\377\4\0\303\6$W\376\377\5\0TABLE\7\0"..., 2064) = 2064
read(9, "38C00004$$\376\377\4\0\303\6%(\4\0\303\6%(\3\0LOB\7\0x"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\6%G\376\377\5\0TABLE\7\0xn\n\24\25\10\34\7"..., 2064) = 2064
read(9, "VALID\1\0N\1\0N\1\0N\3\0SYS\30\0GV_OLAPI_SE"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\1\0N\1\0N\3\0SYS\31\0OLAPI_MEM"..., 2064) = 2064
read(9, "n\n\24\25\t\n\7\0xn\n\24\25\t\n\23\0002010-10-20:20:0"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\4\0TYPE\7\0xn\n\24\25\t\v\7\0xn\n\24\25"..., 2064) = 2064
read(9, "\16\23\0002010-10-20:20:08:12\5\0VALID\1\0N"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\7\0xn\n\24\25\t\25\23\0002010-10-20:"..., 2064) = 2064
read(9, "ITIONSTRUCT\376\377\4\0\303\6(\4\376\377\4\0TYPE\7\0xn\n"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\4\0VIEW\7\0xn\n\24\25\t\27\7\0xn\n\24\25"..., 2064) = 2064
read(9, " PARTITION\7\0xn\v\7\0238\10\7\0xn\v\7\0238\10\23\00020"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0-11-07:18:55:08\5\0VALID"..., 2064) = 2064
read(9, "ITION\7\0xn\v\7\0238\n\7\0xn\v\7\0238\n\23\0002010-11"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\000010-11-07:22:52:09\5\0VA"..., 2064) = 2064
read(9, "-11-07:22:52:10\5\0VALID\1\0N\1\0N\1\0N\6"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0T_SOO_BUFFER_BUSY\376\377\4\0\303"..., 2064) = 2064
read(9, "\0xn\n\36\27\5\33\7\0xn\n\37\27\6\5\23\0002010-10-23:01"..., 1958) = 1958
read(9, "\7\333\0\0\6\0\0\0\0\0\6+ \17\0TABLE PARTITION\7\0"..., 2064) = 2064
read(9, "09\5\0VALID\1\0N\1\0N\1\0N\3\0SYS\27\0WRH$_DB"..., 1477) = 1477
write(7, "0-09-29:17:56:12\5\0VALID\1\0N\1\0N\1\0N"..., 4096) = 4096
write(7, "05465\376\377\4\0\303\6\37\\\4\0\303\6\37\\\5\0INDEX\7\0xn\t\35"..., 61440) = 61440

/* 这里exp首先累计(accumulates)读取了65536 bytes的数据到缓存中,然后以2次write写出这些记录到导出文件中
   换而言之可以把recordlength看做direct patch时的buffer size
*/

那么recordlength是如何影响exp的效率的呢?由以上演示可知在使用direct直接路径读取方式时,recordlength并不影响读取(read),不管我们设置如何的recordlength,exp进程所需做的read总工作量都是一样的。区别在于write的次数和单次写出的数据量,以不设置recordlength为例,其写出8192字节数据需要做2次的write,则当dump文件为600MB时需要写出153600次;而设置recordlength为65535时,其写出(4096+61440)=65536也仅需要做2次write call,当dump文件为600MB时仅需要写出19200次。可知当使用更大的recordlength时可以有效减少exp作业所需的CPU时间和实际IO次数,以极大地加速导出速度;表现到IO层的话,就是用户可以显示地使用iostat等工具看到在导出阶段的写出IO大幅上升。使用recordlength的直接代价是exp进程会消耗使用更多的内存(一般在100~200k左右),以现在的眼光看来这点内存无关紧要。

需要注意的是recordlength现在存在一个最大值(maximum)为65535,设置超过65536的recordlength,exp程序都会返回如:Note: RECORDLENGTH=65536 truncated to 65535的信息;早期版本(734 or 8i)中不存在这个限制,也说明了exp的开发人员逐渐意识到大于65535的 recordlength无益于加速导出。

metalink文档[ID 134966.1]指出了如何判断recordlength的默认值:

Problem Description
——————-
You want to export the entire database and move it to a different platform.
The RECORDLENGTH parameter must be specified during the export since each
platform has a different default.
How do you determine the default RECORDLENGTH value for each platform?
Solution Description
——————–
Look for the BUFSIZ-Parameter in the File /usr/include/stdio.h file to determine
the default size of the output record length.
If no value is specified for the BUFSIZ parameter then a default of 512 bytes
will be used.
Explanation
———–
If the RECORDLENGTH parameter is not explicitly set on EXP/IMP, ORACLE will use the
value specified for BUFSIZ in the /usr/include/stdio.h file to determine the
size of it’s output record length.
The BUFFER parameter applies ONLY to conventional path Export. It has no effect on a direct path Export. This BUFFER parameter specifies the size (in bytes) of the buffer used to fetch rows. It determines the maximum number of rows in an array, fetched by Export. For direct path Export, use the RECORDLENGTH parameter to specify the size of the buffer that Export uses for writing to the export file.

The RECORDLENGTH parameter specifies the length (in bytes) of the file record. You can use this parameter to specify the size of the Export I/O buffer (highest value is 64 kb). Changing the RECORDLENGTH parameter affects only the size of data that accumulates before writing to disk. It does not affect the operating system file block size. If you do not define this parameter, it defaults to your platform-dependent value for BUFSIZ (1024 bytes in most cases).

BUFSIZ本身是UNIX/LINUX系统中控制I/O buffersize的参数,有兴趣研究的话可以参考著名的apue书(W.Richard Stevens的<Advanced Programming in the UNIX Environment>,这本书可以做任何人的Unix C启蒙书:

The value of BUFSIZ is chosen on each system so as to make stream I/O efficient. So it is a good idea to use BUFSIZ as the size for the buffer when you call setvbuf. Actually, you can get an even better value to use for the buffer size by means of the fstat system call: it is found in the st_blksize field of the file attributes.Sometimes people also use BUFSIZ as the allocation size of buffers used for related purposes, such as strings used to receive a line of input with fgets (see section 12.8 Character Input). There is no particular reason to use BUFSIZ for this instead of any other integer, except that it might lead to doing I/O in chunks of an efficient size.

Comment

*

沪ICP备14014813号-2

沪公网安备 31010802001379号