[linux-audio-dev] more preallocation vs no prealloc / async vs sync tests.

New Message Reply About this list Date view Thread view Subject view Author view Other groups

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);
}


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Fri Apr 21 2000 - 17:26:43 EEST