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