Subject: [linux-audio-dev] more preallocation vs no prealloc / async vs sync tests.
From: Benno Senoner (sbenno_AT_gardena.net)
Date: Fri Apr 21 2000 - 17:17:45 EEST
Hi, more realworld of writing / vs rewriting (without O_TRUNC) to files
performance:
I enchanced hdtest.c a bit in order to recognize the "notrunc" flag which opens
the file without O_TRUNC (you have to run a first test with "trunc" in order to
create the files, which are created in an interleaved fashion (by 256k blocks);
I tried even to create them in a linear fashion (write first the entire file1,
then file2 , etc, but I see no big performance difference between the two modes)
(testbox PII400, 256MB RAM, IBM 16GB EIDE UDMA 5400rpm, kernel 2.2.12)
./hdtest 500 async trunc
SINGLE THREADED: 5.856 MByte/sec
MULTI-THREADED: 6.096 MByte/sec
./hdtest 500 async notrunc (rewrite to preallocated files)
SINGLE THREADED: 4.040 MByte/sec
MULTI-THREADED: 4.766 MByte/sec
./hdtest 150 sync trunc
SINGLE THREADED: 1.442 MByte/sec
MULTI-THREADED: 0.121 MByte/sec (floppy-like performance :-) )
./hdtest 150 sync notrunc
SINGLE THREADED: 4.788 MByte/sec
MULTI-THREADED: 1.984 MByte/sec
interesting that preallocation speeds up the O_SYNC mode quite a bit,
although mulithreading is not usable in this mode.
Anyone know what happens here ?
PS: Paul run it on your 10k rpm SCSI disk so that we can do some comparison.
Benno.
------------------------------------------------------------
/* hdtest.c
small async vs O_SYNC / single vs multithreaded disk writing benchmark
by Benno Senoner (sbenno_AT_gardena.net)
the program writes NUMFILES (=20) files simultaneously
compile with : gcc -O2 -o hdtest hdtest.c -lpthread
run with ./hdtest TOTAL_OUTPUT_MEGABYTES <synchmethod> <truncate>
for example: ./hdtest 500 writes a total amount of 500MB of data
<synchmethod> can be either sync (opens with O_SYNC) or async
for O_SYNC output give 'sync' as 2nd argument ( ./hdtest 500 sync )
default is async
<truncate> can be either trunc (opens with O_TRUNC) or notrunc
default is trunc
If you want to run with notrunc, run a session with trunc first
or create the files by hand
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <time.h>
// IO OUTPUT SIZE , default 256k )
#define MYSIZE (262144*4)
#define NUMFILES 20
#define NUMLOOPS (TOTAL_WRITE_SIZE/(MYSIZE*NUMFILES))
void *writer_thread(void *data);
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
int num_active_threads;
int written_bytes;
time_t time1,time2;
char *buf;
int TOTAL_WRITE_SIZE;
void print_status(void);
int main(int argc, char **argv)
{
int i,u;
int res;
int retcode;
int counter=0;
int open_flags;
pthread_t my_thread[NUMFILES];
char filename[200];
int fds[NUMFILES];
buf=(char *)malloc(MYSIZE);
for(i=0;i<MYSIZE;i++) {
buf[i]=0;
}
open_flags=O_WRONLY|O_TRUNC|O_CREAT;
TOTAL_WRITE_SIZE=100*1024*1024;
if(argc >=2) {
TOTAL_WRITE_SIZE=1024*1024*atoi(argv[1]);
}
TOTAL_WRITE_SIZE=MYSIZE*NUMFILES*NUMLOOPS;
printf("TOTAL WRITE SIZE=%d\n",TOTAL_WRITE_SIZE);
if(argc >=3) {
if(!strcmp(argv[2],"sync")) {
open_flags |= O_SYNC;
printf("opening in files in O_SYNC mode\n");
}
}
if(argc >=4 ) {
if(!strcmp(argv[3],"notrunc")) {
open_flags &= ~O_TRUNC;
printf("opening files without O_TRUNC (rewrite mode)\n");
}
}
printf("opening files");
for(i=0;i<NUMFILES;i++) {
printf(".");
fflush(stdout);
sprintf(filename,"outfile%d",i);
fds[i]=open(filename, open_flags, 0777);
if(fds[i]<0) {
fprintf(stderr,"ERROR while opening file '%s'\n",filename);
perror("ERROR: open");
}
}
printf("\n");
sync();
sleep(2);
printf("SINGLE THREADED WRITING START\n");
time(&time1);
written_bytes=0;
for(u=0;u<NUMLOOPS;u++) {
for(i=0;i<NUMFILES;i++) {
res=write(fds[i],buf,MYSIZE);
if(res != MYSIZE) {
printf("write ERROR: res=%d\n",res);
perror("write");
exit(1);
}
written_bytes += MYSIZE;
if((counter++ & 7)==0) {
print_status();
}
}
}
for(i=0;i<NUMFILES;i++) {
close(fds[i]);
}
sync();
time(&time2);
printf("SINGLE THREADED WRITING END\n");
printf("ELAPSED TIME=%d\n",time2-time1);
printf("EFFECTIVE SPEED=%.3f MByte/sec\n",(double)TOTAL_WRITE_SIZE/(double)(time2-time1)/1000000.0);
sleep(4);
printf("opening files");
for(i=0;i<NUMFILES;i++) {
sprintf(filename,"outfile%d",i);
printf(".");
fflush(stdout);
fds[i]=open(filename, open_flags, 0777);
if(fds[i]<0) {
fprintf(stderr,"ERROR while opening file '%s'\n",filename);
perror("ERROR: open");
}
}
sync();
sleep(2);
printf("\n");
printf("MULTI-THREADED WRITING START\n");
time(&time1);
written_bytes=0;
num_active_threads=NUMFILES;
for(i=0;i<NUMFILES;i++) {
retcode=pthread_create(&my_thread[i],NULL,writer_thread,&fds[i]);
if(retcode) {
fprintf(stderr,"pthread_create of thread %d failed %d\n",i,retcode);
exit(1);
}
}
printf("ALL THREADS FIRED UP, PARENT WAITING FOR FINISH ....\n");
while(1) {
sleep(1);
print_status();
if(num_active_threads == 0) break;
}
sync();
time(&time2);
printf("ELAPSED TIME=%d\n",time2-time1);
printf("EFFECTIVE SPEED=%.3f MByte/sec\n",(double)TOTAL_WRITE_SIZE/(double)(time2-time1)/1000000.0);
printf("MULTI-THREADED WRITING END\n");
printf("PARENT FINISH.\n");
}
void *writer_thread(void *data) {
int myfd;
int i,res;
for(i=0;i<MYSIZE;i++) {
buf[i]=0;
}
myfd=*(int *)data;
//printf("writer_thread: myfd=%d\n",myfd);
for(i=0;i<NUMLOOPS;i++) {
res=write(myfd,buf,MYSIZE);
if(res != MYSIZE) {
printf("write ERROR: res=%d\n",res);
perror("write");
exit(1);
}
pthread_mutex_lock(&my_mutex);
written_bytes += MYSIZE;
pthread_mutex_unlock(&my_mutex);
//if((i & 15)==0) printf("wrote: fd=%d block %d\n",myfd,i);
}
close(myfd);
pthread_mutex_lock(&my_mutex);
num_active_threads--;
pthread_mutex_unlock(&my_mutex);
return(NULL);
}
void print_status(void) {
double percent;
double data_rate;
time_t time3;
time(&time3);
percent=(double)written_bytes/(double)TOTAL_WRITE_SIZE*100.0;
data_rate=(double)written_bytes/(double)(time3-time1)/1000000.0;
printf("wrote bytes=%d done %.1f%% RATE=%.3f MByte/sec %c",written_bytes,percent,data_rate,13);
fflush(stdout);
}
This archive was generated by hypermail 2b28 : Fri Apr 21 2000 - 17:26:43 EEST