stat-perf.c 4.95 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 *  (C) 2012 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

/* stat-perf.c
 *
 * Time how long it takes to issue a stat64() call to the designated file
9 10
 * from every process.  -f causes it to use fstat64() rather than stat64().  
 * -l causes it to use lseek(SEEK_END) instead of stat64().
11
 * -c causes it to create the file from scratch rather than operating on an
12
 *  existing file.  -r issues a realpath() call on the file.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 */

#define _LARGEFILE64_SOURCE

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <mpi.h>
#include <errno.h>
#include <getopt.h>

static char* opt_file = NULL;
static int opt_create = 0;
static int opt_fstat = 0;
33
static int opt_lseek = 0;
34
static int opt_realpath = 0;
35 36 37 38 39 40 41 42 43 44 45 46
static int rank = -1;

static int parse_args(int argc, char **argv);
static void usage(void);

int main(int argc, char **argv)
{
   int fd;
   int ret;
   double stime, etime, elapsed, slowest;
   struct stat64 statbuf;
   int nprocs;
47
   off64_t offset, orig_offset;
48
   char* new_path;
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

   MPI_Init(&argc,&argv);
   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
   MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
   
   /* parse the command line arguments */
   parse_args(argc, argv);

   MPI_Barrier(MPI_COMM_WORLD);

   /* open specified file */
   if(!opt_create)
   {
      fd = open(opt_file, O_RDWR);  
      if(fd < 0)
      {
         perror("open");
         exit(1);
      }
   }
   else
   {
      /* rank 0 create, everyone else open */
      if(rank == 0)
      {
         fd = open(opt_file, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
         if(fd < 0)
         {
            perror("open");
            exit(1);
         }
         MPI_Barrier(MPI_COMM_WORLD);
      }
      else
      {
         MPI_Barrier(MPI_COMM_WORLD);
         fd = open(opt_file, O_RDWR);  
         if(fd < 0)
         {
            perror("open");
            exit(1);
         }
      }
   }

   MPI_Barrier(MPI_COMM_WORLD);
   stime = MPI_Wtime();

97
   ret = 0;
98 99
   if(opt_fstat)
      ret = fstat64(fd, &statbuf);
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
   else if(opt_lseek)
   {
      /* find current position */
      orig_offset = lseek64(fd, 0, SEEK_CUR);
      if(orig_offset < 0)
         ret = -1;
      else
      {
         /* find end of file; this is the size */
         offset = lseek64(fd, 0, SEEK_END);
         if(offset < 0)
            ret = -1;
         else
         {
            /* go back to original position */
            offset = lseek64(fd, orig_offset, SEEK_SET);
            if(offset < 0)
                ret = -1;
         }
      }
   }
121 122 123 124 125 126 127 128
   else if(opt_realpath)
   {
      new_path = realpath(opt_file, NULL);
      if(!new_path)
        ret = -1;
      else
        free(new_path);
   }
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
   else
      ret = stat64(opt_file, &statbuf);

   if(ret != 0)
   {
      perror("stat64 or fstat64");
      exit(1);
   }
   
   etime = MPI_Wtime();

   elapsed = etime-stime;
   ret = MPI_Reduce(&elapsed, &slowest, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
   if(ret != 0)
   {
      fprintf(stderr, "Error: MPI_Reduce() failure.\n");
      exit(1);
   }


   slowest *= 1000.0;

   if(rank == 0)
   {
153
      printf("opt_file: %s, opt_create: %d, opt_fstat: %d, opt_lseek: %d, opt_realpath: %d, nprocs: %d, time: %f ms\n", opt_file, opt_create, opt_fstat, opt_lseek, opt_realpath, nprocs, slowest);
154 155 156 157 158 159 160 161 162 163
   }

   MPI_Finalize();
   return(0);
}

static int parse_args(int argc, char **argv)
{
   int c;
   
164
   while ((c = getopt(argc, argv, "fclr")) != EOF) {
165 166 167 168 169 170 171
      switch (c) {
         case 'c': /* create file */
            opt_create = 1;
            break;
         case 'f': /* fstat instead of stat */
            opt_fstat = 1;
            break;
172 173 174
         case 'l': /* lseek instead of stat */
            opt_lseek = 1;
            break;
175 176 177
         case 'r': /* realpath instead of stat */
            opt_realpath = 1;
            break;
178 179 180 181 182 183 184 185 186 187 188 189 190
         case 'h':
            if (rank == 0)
                usage();
            exit(0);
         case '?': /* unknown */
            if (rank == 0)
                usage();
            exit(1);
         default:
            break;
      }
   }

191
   if(opt_lseek + opt_fstat + opt_realpath > 1)
192
   {
193
      fprintf(stderr, "Error: Only specify one of -l, -f, or -r.\n");
194 195 196 197
      usage();
      exit(1);
   }

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
   if(argc-optind != 1)
   {
      if(rank == 0)
          usage();
      exit(1);
   }

   opt_file = strdup(argv[optind]);
   assert(opt_file);

   return(0);
}

static void usage(void)
{
    printf("Usage: stat-perf [<OPTIONS>...] <FILE NAME>\n");
    printf("\n<OPTIONS> is one or more of\n");
    printf(" -c       create new file to stat\n");
    printf(" -f       use fstat instead of stat\n");
217
    printf(" -l       use lseek instead of stat\n");
218
    printf(" -r       use realpath instead of stat\n");
219 220 221 222 223 224 225 226 227 228 229 230 231 232
    printf(" -h       print this help\n");
}

/*
 * Local variables:
 *  c-indent-level: 3
 *  c-basic-offset: 3
 *  tab-width: 3
 *
 * vim: ts=3
 * End:
 */