Reputation:
I am trying to explore how file system performance can be affected, quite significantly, by the access characteristics of the application. I want to vary the request size from 1KB (1024) to 64KB (65536).
When, i get to 8KB is when i get a write to file error. Am i not allocating enough space?
./test
error writing file (rc = 200704, errno 0)
I am adjusting the 1KB - 64KB size here:
request_size = 32*(1<<13); /* 1KB is 1^10 (or 1<<10) */
So, this should be 8kb = 8192
Should i be requesting 4mb file now? I am not sure what shift that would be?
int main(int c, char *argv[]) {
int fd;
void *buffer, *buffer_aligned;
int i, rc;
unsigned long file_size, request_size;
struct timeval start, stop;
double seconds;
/* allocate a 64KB page-aligned buffer */
buffer = malloc(65536+4096);
buffer_aligned = buffer+(4096-(((unsigned long)buffer)%4096));
/* write a 1MB file with 32KB requests */
fd = open("foo", O_CREAT|O_RDWR, 0644);
file_size = 1*(1<<20); /* 1MB is 2^20 (or 1<<20). 1GB is 2^30 (or 1<<30) */
request_size = 32*(1<<13); /* 1KB is 1^10 (or 1<<10) */
gettimeofday(&start, NULL);
for (i=0; i<file_size/request_size; i++) {
if ((rc=write(fd, buffer_aligned, request_size))!=request_size) {
fprintf(stderr, "error writing file (rc = %i, errno %i)\n", rc, errno);
return 1;
}
}
gettimeofday(&stop, NULL);
seconds = ((stop.tv_sec*1e6+stop.tv_usec)-(start.tv_sec*1e6+start.tv_usec))/1e6;
printf("file size is %uMB\n", file_size>>20);
printf("request size is %uKB\n", request_size>>13);
printf("elapsed time is %.2lf seconds\n", seconds);
printf("bandwidth is %.2lf MB/sec\n", file_size/seconds/(1<<20));
close(fd);
/* free buffer */
free(buffer);
return 0;
}
wouldnt this be 8KB?
request_size = 32*(1<<13); /* 1KB is 1^10 (or 1<<10) */
Upvotes: 1
Views: 117
Reputation: 10799
What's likely happening is that the amount of data you're writing in that one call to write
has become too much for it to always be completely written on the first call. From the GNU libc documentation for write
:
The return value is the number of bytes actually written. This may be size, but can always be smaller. Your program should always call write in a loop, iterating until all the data is written.
(I've attempted to check documentation for other libc implementations, but none of them describe this behaviour in the same detail as GNU. They simply say that the function "attempts to write nbytes of data, and returns the number of bytes written". Some mention that it depends on whether the file descriptor is in non-blocking mode. In any case, write
usually maps directly to an operating system call, so the behaviour is OS dependant, too.)
So basically, you'll need to put a loop around write
, checking until it has written request_size
bytes. Something like:
unsigned long data_remaining = request_size;
void *data_offset = buffer_aligned;
while (data_remaining > 0)
{
rc = write(fd, data_offset, data_remaining);
if (rc == -1) {
fprintf(stderr, "error writing file (rc = %i, errno %i)\n", rc, errno);
return 1;
}
data_remaining -= rc;
data_offset += rc; /* you don't care about the data being written, so this is kind of unnecessary in your case */
}
Upvotes: 1