Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * io/benchmark_random_block_access.cpp 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2009 Johannes Singler <singler@ira.uka.de> 00007 * Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.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 /* 00015 example gnuplot command for the output of this program: 00016 (x-axis: offset in GiB, y-axis: bandwidth in MiB/s) 00017 00018 plot \ 00019 "disk.log" using ($2/1024):($7) w l title "read", \ 00020 "disk.log" using ($2/1024):($4) w l title "write" 00021 */ 00022 00023 #include <iomanip> 00024 #include <vector> 00025 00026 #include <stxxl/io> 00027 #include <stxxl/mng> 00028 00029 #ifndef BOOST_MSVC 00030 #include <unistd.h> 00031 #endif 00032 00033 00034 using stxxl::request_ptr; 00035 using stxxl::file; 00036 using stxxl::timestamp; 00037 00038 00039 #ifdef BLOCK_ALIGN 00040 #undef BLOCK_ALIGN 00041 #endif 00042 00043 #define BLOCK_ALIGN 4096 00044 00045 00046 #define KB (1024) 00047 #define MB (1024 * 1024) 00048 #define GB (1024 * 1024 * 1024) 00049 00050 void usage(const char * argv0) 00051 { 00052 std::cout << "Usage: " << argv0 << " span block_size num_accesses [i][r][w]" << std::endl; 00053 std::cout << " 'span' is given in MiB" << std::endl; 00054 std::cout << " 'block_size' is given in KiB, must be a multiple of 4" << std::endl; 00055 std::cout << " (only a few block sizes are compiled in)" << std::endl; 00056 std::cout << " [i]nitialize, [r]ead, and/or [w]rite (one string)" << std::endl; 00057 exit(-1); 00058 } 00059 00060 struct print_number 00061 { 00062 int n; 00063 00064 print_number(int n) : n(n) { } 00065 00066 void operator () (stxxl::request_ptr) 00067 { 00068 //std::cout << n << " " << std::flush; 00069 } 00070 }; 00071 00072 template <unsigned BlockSize> 00073 void run_test(stxxl::int64 span, stxxl::int64 num_blocks, bool do_init, bool do_read, bool do_write) 00074 { 00075 const unsigned raw_block_size = BlockSize; 00076 00077 typedef stxxl::typed_block<raw_block_size, unsigned> block_type; 00078 typedef stxxl::BID<raw_block_size> BID_type; 00079 00080 stxxl::int64 num_blocks_in_span = stxxl::div_ceil(span, raw_block_size); 00081 num_blocks = stxxl::STXXL_MIN(num_blocks, num_blocks_in_span); 00082 00083 block_type * buffer = new block_type; 00084 request_ptr * reqs = new request_ptr[num_blocks_in_span]; 00085 std::vector<BID_type> blocks; 00086 00087 //touch data, so it is actually allocated 00088 00089 try { 00090 STXXL_DEFAULT_ALLOC_STRATEGY alloc; 00091 00092 blocks.resize(num_blocks_in_span); 00093 stxxl::block_manager::get_instance()->new_blocks(alloc, blocks.begin(), blocks.end()); 00094 00095 std::cout << "# Span size: " 00096 << stxxl::add_IEC_binary_multiplier(span, "B") << " (" 00097 << num_blocks_in_span << " blocks of " 00098 << stxxl::add_IEC_binary_multiplier(raw_block_size, "B") << ")" << std::endl; 00099 00100 double begin, end, elapsed; 00101 00102 if (do_init) 00103 { 00104 begin = timestamp(); 00105 std::cout << "First fill up space by writing sequentially..." << std::endl; 00106 for (unsigned j = 0; j < num_blocks_in_span; j++) 00107 reqs[j] = buffer->write(blocks[j]); 00108 wait_all(reqs, num_blocks_in_span); 00109 end = timestamp(); 00110 elapsed = end - begin; 00111 std::cout << "Written " 00112 << std::setw(12) << num_blocks_in_span << " blocks in " << std::fixed << std::setw(9) << std::setprecision(2) << elapsed << " seconds: " 00113 << std::setw(9) << std::setprecision(1) << (double(num_blocks_in_span) / elapsed) << " blocks/s " 00114 << std::setw(7) << std::setprecision(1) << (double(num_blocks_in_span * raw_block_size) / MB / elapsed) << " MiB/s write " << std::endl; 00115 } 00116 00117 std::cout << "Random block access..." << std::endl; 00118 00119 srand(time(NULL)); 00120 std::random_shuffle(blocks.begin(), blocks.end()); 00121 00122 begin = timestamp(); 00123 if (do_read) 00124 { 00125 for (unsigned j = 0; j < num_blocks; j++) 00126 reqs[j] = buffer->read(blocks[j], print_number(j)); 00127 wait_all(reqs, num_blocks); 00128 00129 end = timestamp(); 00130 elapsed = end - begin; 00131 std::cout << "Read " << num_blocks << " blocks in " << std::fixed << std::setw(5) << std::setprecision(2) << elapsed << " seconds: " 00132 << std::setw(5) << std::setprecision(1) << (double(num_blocks) / elapsed) << " blocks/s " 00133 << std::setw(5) << std::setprecision(1) << (double(num_blocks * raw_block_size) / MB / elapsed) << " MiB/s read" << std::endl; 00134 } 00135 00136 std::random_shuffle(blocks.begin(), blocks.end()); 00137 00138 begin = timestamp(); 00139 if (do_write) 00140 { 00141 for (unsigned j = 0; j < num_blocks; j++) 00142 reqs[j] = buffer->write(blocks[j], print_number(j)); 00143 wait_all(reqs, num_blocks); 00144 00145 end = timestamp(); 00146 elapsed = end - begin; 00147 std::cout << "Written " << num_blocks << " blocks in " << std::fixed << std::setw(5) << std::setprecision(2) << elapsed << " seconds: " 00148 << std::setw(5) << std::setprecision(1) << (double(num_blocks) / elapsed) << " blocks/s " 00149 << std::setw(5) << std::setprecision(1) << (double(num_blocks * raw_block_size) / MB / elapsed) << " MiB/s write " << std::endl; 00150 } 00151 } 00152 catch (const std::exception & ex) 00153 { 00154 std::cout << std::endl; 00155 STXXL_ERRMSG(ex.what()); 00156 } 00157 00158 //stxxl::block_manager::get_instance()->delete_blocks(blocks.begin(), blocks.end()); 00159 00160 delete[] reqs; 00161 delete buffer; 00162 } 00163 00164 int main(int argc, char * argv[]) 00165 { 00166 if (argc < 4) 00167 usage(argv[0]); 00168 00169 stxxl::int64 span = stxxl::int64(MB) * stxxl::int64(atoi(argv[1])); 00170 unsigned block_size = atoi(argv[2]); 00171 stxxl::int64 num_blocks = stxxl::int64(atoi(argv[3])); 00172 00173 bool do_init = false, do_read = false, do_write = false; 00174 00175 if (argc == 5 && (strstr(argv[4], "i") != NULL)) 00176 do_init = true; 00177 00178 if (argc == 5 && (strstr(argv[4], "r") != NULL)) 00179 do_read = true; 00180 00181 if (argc == 5 && (strstr(argv[4], "w") != NULL)) 00182 do_write = true; 00183 00184 switch (block_size) 00185 { 00186 #define run(bs) run_test<bs>(span, num_blocks, do_init, do_read, do_write) 00187 case 4: 00188 run(4 * KB); 00189 break; 00190 case 8: 00191 run(8 * KB); 00192 break; 00193 case 16: 00194 run(16 * KB); 00195 break; 00196 case 32: 00197 run(32 * KB); 00198 break; 00199 case 64: 00200 run(64 * KB); 00201 break; 00202 case 128: 00203 run(128 * KB); 00204 break; 00205 case 256: 00206 run(256 * KB); 00207 break; 00208 case 512: 00209 run(512 * KB); 00210 break; 00211 case 1024: 00212 run(1024 * KB); 00213 break; 00214 case 2048: 00215 run(2048 * KB); 00216 break; 00217 case 4096: 00218 run(4096 * KB); 00219 break; 00220 default: 00221 std::cerr << "unsupported block_size " << block_size << std::endl; 00222 #undef run 00223 } 00224 00225 return 0; 00226 } 00227 00228 // vim: et:ts=4:sw=4