Stxxl  1.4.0
utils/createdisks.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  utils/createdisks.cpp
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2003 Roman Dementiev <dementiev@mpi-sb.mpg.de>
00007  *  Copyright (C) 2007 Andreas Beckmann <beckmann@mpi-inf.mpg.de>
00008  *
00009  *  Distributed under the Boost Software License, Version 1.0.
00010  *  (See accompanying file LICENSE_1_0.txt or copy at
00011  *  http://www.boost.org/LICENSE_1_0.txt)
00012  **************************************************************************/
00013 
00014 #include <cstdio>
00015 #include <iomanip>
00016 #include <vector>
00017 
00018 #include <stxxl/io>
00019 #include <stxxl/aligned_alloc>
00020 
00021 #ifndef BOOST_MSVC
00022  #include <unistd.h>
00023 #endif
00024 
00025 
00026 using stxxl::request_ptr;
00027 using stxxl::file;
00028 using stxxl::timestamp;
00029 
00030 
00031 #ifdef BLOCK_ALIGN
00032  #undef BLOCK_ALIGN
00033 #endif
00034 
00035 #define BLOCK_ALIGN  4096
00036 
00037 #define NOREAD
00038 
00039 //#define DO_ONLY_READ
00040 
00041 #define POLL_DELAY 1000
00042 
00043 #define RAW_ACCESS
00044 
00045 //#define WATCH_TIMES
00046 
00047 #define CHECK_AFTER_READ 0
00048 
00049 
00050 #ifdef WATCH_TIMES
00051 void watch_times(request_ptr reqs[], unsigned n, double * out)
00052 {
00053     bool * finished = new bool[n];
00054     unsigned count = 0;
00055     unsigned i = 0;
00056     for (i = 0; i < n; i++)
00057         finished[i] = false;
00058 
00059 
00060     while (count != n)
00061     {
00062         usleep(POLL_DELAY);
00063         i = 0;
00064         for (i = 0; i < n; i++)
00065         {
00066             if (!finished[i])
00067                 if (reqs[i]->poll())
00068                 {
00069                     finished[i] = true;
00070                     out[i] = timestamp();
00071                     count++;
00072                 }
00073         }
00074     }
00075     delete[] finished;
00076 }
00077 
00078 
00079 void out_stat(double start, double end, double * times, unsigned n, const std::vector<std::string> & names)
00080 {
00081     for (unsigned i = 0; i < n; i++)
00082     {
00083         std::cout << i << " " << names[i] << " took " <<
00084         100. * (times[i] - start) / (end - start) << " %" << std::endl;
00085     }
00086 }
00087 #endif
00088 
00089 #define MB (1024 * 1024)
00090 
00091 int main(int argc, char * argv[])
00092 {
00093     if (argc < 3)
00094     {
00095         STXXL_MSG("Usage: " << argv[0] << " filesize_in_MiB filename1 [filename2 [filename3 ...]]");
00096         return -1;
00097     }
00098 
00099     stxxl::int64 offset = 0;
00100     stxxl::int64 length = stxxl::int64(atoi(argv[1])) * MB;
00101     stxxl::int64 endpos = offset + length;
00102 
00103     std::vector<std::string> disks_arr;
00104 
00105     for (int ii = 2; ii < argc; ++ii)
00106     {
00107         unlink(argv[ii]);
00108         std::cout << "# Add disk: " << argv[ii] << std::endl;
00109         disks_arr.push_back(argv[ii]);
00110     }
00111 
00112     const unsigned ndisks = disks_arr.size();
00113 
00114 
00115 #ifdef BOOST_MSVC
00116     unsigned buffer_size = 64 * MB;
00117 #else
00118     unsigned buffer_size = 256 * MB;
00119 #endif
00120     const unsigned buffer_size_int = buffer_size / sizeof(int);
00121 
00122     unsigned chunks = 2;
00123     const unsigned chunk_size = buffer_size / chunks;
00124     const unsigned chunk_size_int = chunk_size / sizeof(int);
00125 
00126     unsigned i = 0, j = 0;
00127 
00128     int * buffer = (int *)stxxl::aligned_alloc<BLOCK_ALIGN>(buffer_size * ndisks);
00129     file ** disks = new file *[ndisks];
00130     request_ptr * reqs = new request_ptr[ndisks * chunks];
00131 #ifdef WATCH_TIMES
00132     double * r_finish_times = new double[ndisks];
00133     double * w_finish_times = new double[ndisks];
00134 #endif
00135 
00136     for (i = 0; i < ndisks * buffer_size_int; i++)
00137         buffer[i] = i;
00138 
00139     for (i = 0; i < ndisks; i++)
00140     {
00141 #ifdef BOOST_MSVC
00142  #ifdef RAW_ACCESS
00143         disks[i] = new stxxl::wincall_file(disks_arr[i],
00144                                            file::CREAT | file::RDWR | file::DIRECT, i);
00145  #else
00146         disks[i] = new stxxl::wincall_file(disks_arr[i],
00147                                            file::CREAT | file::RDWR, i);
00148  #endif
00149 #else
00150  #ifdef RAW_ACCESS
00151         disks[i] = new stxxl::syscall_file(disks_arr[i],
00152                                            file::CREAT | file::RDWR | file::DIRECT, i);
00153  #else
00154         disks[i] = new stxxl::syscall_file(disks_arr[i],
00155                                            file::CREAT | file::RDWR, i);
00156  #endif
00157 #endif
00158     }
00159 
00160     while (offset < endpos)
00161     {
00162         const unsigned current_block_size = length ? std::min<stxxl::int64>(buffer_size, endpos - offset) : buffer_size;
00163         const unsigned current_chunk_size = current_block_size / chunks;
00164 
00165         std::cout << "Disk offset " << std::setw(7) << offset / MB << " MiB: " << std::fixed;
00166 
00167         double begin = timestamp(), end;
00168 
00169 #ifndef DO_ONLY_READ
00170         for (i = 0; i < ndisks; i++)
00171         {
00172             for (j = 0; j < chunks; j++)
00173                 reqs[i * chunks + j] =
00174                     disks[i]->awrite(buffer + buffer_size_int * i + j * chunk_size_int,
00175                                      offset + j * current_chunk_size,
00176                                      current_chunk_size,
00177                                      stxxl::default_completion_handler());
00178         }
00179 
00180  #ifdef WATCH_TIMES
00181         watch_times(reqs, ndisks, w_finish_times);
00182  #else
00183         wait_all(reqs, ndisks * chunks);
00184  #endif
00185 
00186         end = timestamp();
00187 
00188 #if 0
00189         std::cout << "WRITE\nDisks: " << ndisks
00190                   << " \nElapsed time: " << end - begin
00191                   << " \nThroughput: " << int(double(buffer_size * ndisks) / MB / (end - begin))
00192                   << " MiB/s \nPer one disk:"
00193                   << int((buffer_size) / MB / (end - begin)) << " MiB/s"
00194                   << std::endl;
00195 #endif
00196 
00197  #ifdef WATCH_TIMES
00198         out_stat(begin, end, w_finish_times, ndisks, disks_arr);
00199  #endif
00200         std::cout << std::setw(7) << int(double(current_block_size) / MB / (end - begin)) << " MiB/s,";
00201 #endif
00202 
00203 
00204 #ifndef NOREAD
00205         begin = timestamp();
00206 
00207         for (i = 0; i < ndisks; i++)
00208         {
00209             for (j = 0; j < chunks; j++)
00210                 reqs[i * chunks + j] = disks[i]->aread(buffer + buffer_size_int * i + j * chunk_size_int,
00211                                                        offset + j * current_chunk_size,
00212                                                        current_chunk_size,
00213                                                        stxxl::default_completion_handler());
00214         }
00215 
00216  #ifdef WATCH_TIMES
00217         watch_times(reqs, ndisks, r_finish_times);
00218  #else
00219         wait_all(reqs, ndisks * chunks);
00220  #endif
00221 
00222         end = timestamp();
00223 
00224 #if 0
00225         std::cout << "READ\nDisks: " << ndisks
00226                   << " \nElapsed time: " << end - begin
00227                   << " \nThroughput: " << int(double(buffer_size * ndisks) / MB / (end - begin))
00228                   << " MiB/s \nPer one disk:"
00229                   << int(double(buffer_size) / MB / (end - begin)) << " MiB/s"
00230                   << std::endl;
00231 #endif
00232 
00233         std::cout << int(double(current_block_size) / MB / (end - begin)) << " MiB/s" << std::endl;
00234 
00235 #ifdef WATCH_TIMES
00236         out_stat(begin, end, r_finish_times, ndisks, disks_arr);
00237 #endif
00238 
00239         if (CHECK_AFTER_READ) {
00240             for (int i = 0; unsigned(i) < ndisks * buffer_size_int; i++)
00241             {
00242                 if (buffer[i] != i)
00243                 {
00244                     int ibuf = i / buffer_size_int;
00245                     int pos = i % buffer_size_int;
00246 
00247                     std::cout << "Error on disk " << ibuf << " position " << std::hex << std::setw(8) << offset + pos * sizeof(int)
00248                               << "  got: " << std::hex << std::setw(8) << buffer[i] << " wanted: " << std::hex << std::setw(8) << i
00249                               << std::dec << std::endl;
00250 
00251                     i = (ibuf + 1) * buffer_size_int; // jump to next
00252                 }
00253             }
00254         }
00255 #else
00256         std::cout << std::endl;
00257 #endif
00258 
00259         offset += current_block_size;
00260     }
00261 
00262 #ifdef WATCH_TIMES
00263     delete[] r_finish_times;
00264     delete[] w_finish_times;
00265 #endif
00266     delete[] reqs;
00267     for (i = 0; i < ndisks; i++)
00268         delete disks[i];
00269     delete[] disks;
00270     stxxl::aligned_dealloc<BLOCK_ALIGN>(buffer);
00271 
00272     return 0;
00273 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines