Stxxl  1.4.0
io/benchmark_configured_disks.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines