Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * io/benchmark_configured_disks.cpp 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2009 Johannes Singler <singler@ira.uka.de> 00007 * 00008 * Distributed under the Boost Software License, Version 1.0. 00009 * (See accompanying file LICENSE_1_0.txt or copy at 00010 * http://www.boost.org/LICENSE_1_0.txt) 00011 **************************************************************************/ 00012 00013 /* 00014 example gnuplot command for the output of this program: 00015 (x-axis: offset in GiB, y-axis: bandwidth in MiB/s) 00016 00017 plot \ 00018 "disk.log" using ($2/1024):($7) w l title "read", \ 00019 "disk.log" using ($2/1024):($4) w l title "write" 00020 */ 00021 00022 #include <iomanip> 00023 #include <vector> 00024 00025 #include <stxxl/io> 00026 #include <stxxl/mng> 00027 00028 #ifndef BOOST_MSVC 00029 #include <unistd.h> 00030 #endif 00031 00032 00033 using stxxl::request_ptr; 00034 using stxxl::file; 00035 using stxxl::timestamp; 00036 00037 00038 #ifdef BLOCK_ALIGN 00039 #undef BLOCK_ALIGN 00040 #endif 00041 00042 #define BLOCK_ALIGN 4096 00043 00044 #define POLL_DELAY 1000 00045 00046 #define CHECK_AFTER_READ 0 00047 00048 00049 #define MB (1024 * 1024) 00050 #define GB (1024 * 1024 * 1024) 00051 00052 void usage(const char * argv0) 00053 { 00054 std::cout << "Usage: " << argv0 << " length step [r|w]" << std::endl; 00055 std::cout << " 'length' is given in GiB, 'step' size in MiB" << std::endl; 00056 std::cout << " length == 0 implies till end of space (please ignore the write error)" << std::endl; 00057 exit(-1); 00058 } 00059 00060 int main(int argc, char * argv[]) 00061 { 00062 if (argc < 3) 00063 usage(argv[0]); 00064 00065 stxxl::int64 offset = 0; 00066 stxxl::int64 length = stxxl::int64(GB) * stxxl::int64(atoi(argv[1])); 00067 stxxl::int64 step_size = stxxl::int64(MB) * stxxl::int64(atoi(argv[2])); 00068 stxxl::int64 endpos = offset + length; 00069 00070 bool do_read = true, do_write = true; 00071 00072 if (argc == 4 && (strcmp("r", argv[3]) == 0 || strcmp("R", argv[3]) == 0)) 00073 do_write = false; 00074 00075 if (argc == 4 && (strcmp("w", argv[3]) == 0 || strcmp("W", argv[3]) == 0)) 00076 do_read = false; 00077 00078 const unsigned raw_block_size = 8 * MB; 00079 const unsigned block_size = raw_block_size / sizeof(int); 00080 00081 typedef stxxl::typed_block<raw_block_size, unsigned> block_type; 00082 typedef stxxl::BID<raw_block_size> BID_type; 00083 00084 unsigned num_blocks_per_step = stxxl::div_ceil(step_size, raw_block_size); 00085 step_size = num_blocks_per_step * raw_block_size; 00086 00087 block_type * buffer = new block_type[num_blocks_per_step]; 00088 request_ptr * reqs = new request_ptr[num_blocks_per_step]; 00089 std::vector<BID_type> blocks; 00090 double totaltimeread = 0, totaltimewrite = 0; 00091 stxxl::int64 totalsizeread = 0, totalsizewrite = 0; 00092 00093 std::cout << "# Step size: " 00094 << stxxl::add_IEC_binary_multiplier(step_size, "B") << " (" 00095 << num_blocks_per_step << " blocks of " 00096 << stxxl::add_IEC_binary_multiplier(raw_block_size, "B") << ")" << std::endl; 00097 00098 //touch data, so it is actually allcoated 00099 for (unsigned j = 0; j < num_blocks_per_step; ++j) 00100 for (unsigned i = 0; i < block_size; ++i) 00101 buffer[j][i] = j * block_size + i; 00102 00103 try { 00104 STXXL_DEFAULT_ALLOC_STRATEGY alloc; 00105 while (offset < endpos) 00106 { 00107 const stxxl::int64 current_step_size = std::min<stxxl::int64>(step_size, endpos - offset); 00108 #if CHECK_AFTER_READ 00109 const stxxl::int64 current_step_size_int = current_step_size / sizeof(int); 00110 #endif 00111 const unsigned current_num_blocks_per_step = stxxl::div_ceil(current_step_size, raw_block_size); 00112 00113 std::cout << "Offset " << std::setw(7) << offset / MB << " MiB: " << std::fixed; 00114 00115 stxxl::unsigned_type num_total_blocks = blocks.size(); 00116 blocks.resize(num_total_blocks + current_num_blocks_per_step); 00117 stxxl::block_manager::get_instance()->new_blocks(alloc, blocks.begin() + num_total_blocks, blocks.end()); 00118 00119 double begin = timestamp(), end, elapsed; 00120 00121 if (do_write) 00122 { 00123 for (unsigned j = 0; j < current_num_blocks_per_step; j++) 00124 reqs[j] = buffer[j].write(blocks[num_total_blocks + j]); 00125 00126 wait_all(reqs, current_num_blocks_per_step); 00127 00128 end = timestamp(); 00129 elapsed = end - begin; 00130 totalsizewrite += current_step_size; 00131 totaltimewrite += elapsed; 00132 } 00133 else 00134 elapsed = 0.0; 00135 00136 std::cout << std::setw(5) << std::setprecision(1) << (double(current_step_size) / MB / elapsed) << " MiB/s write, "; 00137 00138 00139 begin = timestamp(); 00140 00141 if (do_read) 00142 { 00143 for (unsigned j = 0; j < current_num_blocks_per_step; j++) 00144 reqs[j] = buffer[j].read(blocks[num_total_blocks + j]); 00145 00146 wait_all(reqs, current_num_blocks_per_step); 00147 00148 end = timestamp(); 00149 elapsed = end - begin; 00150 totalsizeread += current_step_size; 00151 totaltimeread += elapsed; 00152 } 00153 else 00154 elapsed = 0.0; 00155 00156 std::cout << std::setw(5) << std::setprecision(1) << (double(current_step_size) / MB / elapsed) << " MiB/s read" << std::endl; 00157 00158 #if CHECK_AFTER_READ 00159 for (unsigned j = 0; j < current_num_blocks_per_step; j++) 00160 { 00161 for (unsigned i = 0; i < block_size; i++) 00162 { 00163 if (buffer[j][i] != j * block_size + i) 00164 { 00165 int ibuf = i / current_step_size_int; 00166 int pos = i % current_step_size_int; 00167 00168 std::cout << "Error on disk " << ibuf << " position " << std::hex << std::setw(8) << offset + pos * sizeof(int) 00169 << " got: " << std::hex << std::setw(8) << buffer[j][i] << " wanted: " << std::hex << std::setw(8) << (j * block_size + i) 00170 << std::dec << std::endl; 00171 00172 i = (ibuf + 1) * current_step_size_int; // jump to next 00173 } 00174 } 00175 } 00176 #endif 00177 00178 offset += current_step_size; 00179 } 00180 } 00181 catch (const std::exception & ex) 00182 { 00183 std::cout << std::endl; 00184 STXXL_ERRMSG(ex.what()); 00185 } 00186 00187 std::cout << "=============================================================================================" << std::endl; 00188 std::cout << "# Average over " << std::setw(7) << totalsizewrite / MB << " MiB: "; 00189 std::cout << std::setw(5) << std::setprecision(1) << (double(totalsizewrite) / MB / totaltimewrite) << " MiB/s write, "; 00190 std::cout << std::setw(5) << std::setprecision(1) << (double(totalsizeread) / MB / totaltimeread) << " MiB/s read" << std::endl; 00191 00192 delete[] reqs; 00193 delete[] buffer; 00194 00195 return 0; 00196 }