Stxxl
1.4.0
|
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 }