00001 /* 00002 writev test program 00003 AUP2, Sec. 2.15 (not in book) 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 #include <sys/uio.h> 00023 00024 #define REPS 50000 00025 #define PIECES 16 00026 #define PIECE_SIZE 200 00027 00028 int main(void) 00029 { 00030 int i, fd, count, /*fillerlen,*/ bufsize, iovcnt; 00031 ssize_t n; 00032 char *piece[PIECES]; 00033 #if 0 00034 struct data1 { 00035 int num; 00036 char s[20]; 00037 } d1, d3; 00038 struct data2 { 00039 int num; 00040 char s[50]; 00041 } d2; 00042 char *buf, *filler; 00043 #endif 00044 struct iovec v[PIECES]; 00045 00046 #ifdef BSD_DERIVED 00047 #define IOV_MAX 1024 /* sys/uio.h defines UIO_MAXIOV, but only if _KERNEL is defined */ 00048 #endif 00049 iovcnt = PIECES; 00050 if (iovcnt > IOV_MAX) 00051 iovcnt = IOV_MAX; 00052 for (i = 0; i < iovcnt; i++) { 00053 ec_null( piece[i] = malloc(PIECE_SIZE) ) 00054 memset(piece[i], 123, PIECE_SIZE); 00055 v[i].iov_base = piece[i]; 00056 v[i].iov_len = PIECE_SIZE; 00057 } 00058 printf("iovcnt = %d; piece size = %d; reps = %d\n", 00059 iovcnt, PIECE_SIZE, REPS); 00060 00061 printf("IOV_MAX = %ld; SSIZE_MAX = %ld\n", 00062 (long)IOV_MAX, (long)SSIZE_MAX); 00063 00064 printf("sizeof(int) = %d;BUFSIZ = %d\n", 00065 sizeof(int), BUFSIZ); 00066 00067 ec_neg1( fd = open("a.tmp", O_RDWR | O_CREAT | O_TRUNC, PERM_FILE) ) 00068 /* 00069 We would like a universal way to determine the best buffer size. _PC_ALLOC_SIZE_MIN 00070 (assuming that's even the right symbol) is optional, so not universal. 00071 */ 00072 bufsize = 1024; 00073 /* 00074 #ifdef FREEBSD 00075 bufsize = 4096; 00076 #else 00077 bufsize = fpathconf(fd, _PC_ALLOC_SIZE_MIN); 00078 printf("_PC_ALLOC_SIZE_MIN = %d\n", bufsize); 00079 #endif 00080 */ 00081 00082 #if 0 00083 ec_null( filler = malloc(bufsize) ) 00084 ec_null( buf = malloc(bufsize) ) 00085 00086 d1.num = 123; 00087 strcpy(d1.s, "hello"); 00088 d2.num = 456; 00089 strcpy(d2.s, "goodbye"); 00090 d3.num = 789; 00091 strcpy(d3.s, "thankyou"); 00092 memset(filler, 0, bufsize); 00093 fillerlen = bufsize - sizeof(d1) - sizeof(d2) - sizeof(d3); 00094 00095 v[0].iov_base = &d1; 00096 v[0].iov_len = sizeof(d1); 00097 v[1].iov_base = &d2; 00098 v[1].iov_len = sizeof(d2); 00099 v[2].iov_base = &d3; 00100 v[2].iov_len = sizeof(d3); 00101 v[3].iov_base = filler; 00102 v[3].iov_len = fillerlen; 00103 ec_neg1( n = writev(fd, v, sizeof(v) / sizeof(v[0])) ) 00104 printf("%ld bytes written\n", (long)n); 00105 00106 memset(&d1, 0, sizeof(d1)); 00107 memset(&d2, 0, sizeof(d2)); 00108 memset(&d3, 0, sizeof(d3)); 00109 00110 if (lseek(fd, 0, SEEK_SET) == -1) 00111 syserr("lseek"); 00112 00113 ec_neg1( n = readv(fd, v, sizeof(v) / sizeof(v[0])) ) 00114 printf("%ld bytes read\n", (long)n); 00115 00116 printf("d1: %d %s\n", d1.num, d1.s); 00117 printf("d2: %d %s\n", d2.num, d2.s); 00118 printf("d3: %d %s\n", d3.num, d3.s); 00119 #endif 00120 /* Now do some timing tests. */ 00121 00122 ec_neg1( lseek(fd, 0, SEEK_SET) ) 00123 timestart(); 00124 for (count = 0; count < REPS; count++) 00125 ec_neg1( n = writev(fd, v, iovcnt) ) 00126 timestop("writev"); 00127 printf("Position at end = %ld\n", (long)lseek(fd, 0, SEEK_CUR)); 00128 00129 ec_neg1( lseek(fd, 0, SEEK_SET) ) 00130 timestart(); 00131 for (count = 0; count < REPS; count++) 00132 for (i = 0; i < iovcnt; i++) 00133 ec_neg1( n = write(fd, v[i].iov_base, PIECE_SIZE) ) 00134 timestop("write"); 00135 printf("Position at end = %ld\n", (long)lseek(fd, 0, SEEK_CUR)); 00136 #if 0 00137 ec_neg1( lseek(fd, 0, SEEK_SET) ) 00138 timestart(); 00139 for (count = 0; count < REPS; count++) { 00140 int offset = 0; 00141 memcpy(buf, &d1, sizeof(d1)); 00142 offset += sizeof(d1); 00143 memcpy(buf + offset, &d2, sizeof(d2)); 00144 offset += sizeof(d2); 00145 memcpy(buf + offset, &d3, sizeof(d3)); 00146 offset += sizeof(d3); 00147 assert(fillerlen == bufsize - offset); 00148 memcpy(buf + offset, filler, fillerlen); 00149 offset += fillerlen; 00150 assert(offset == bufsize); 00151 ec_neg1( n = write(fd, buf, bufsize) ) 00152 } 00153 timestop("write (full buffer)"); 00154 printf("Position at end = %ld\n", lseek(fd, 0, SEEK_CUR)); 00155 #endif 00156 ec_neg1( close(fd) ) 00157 exit(EXIT_SUCCESS); 00158 00159 EC_CLEANUP_BGN 00160 exit(EXIT_FAILURE); 00161 EC_CLEANUP_END 00162 }