From 0a3ae3608ada45fc6383beea52495d3fe8144237 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 9 Jun 2009 20:51:07 -0700 Subject: [PATCH] radostool: clean up bench args, usage --- src/radostool.cc | 322 +++++++++++++++++++++++++---------------------- 1 file changed, 173 insertions(+), 149 deletions(-) diff --git a/src/radostool.cc b/src/radostool.cc index aa4a9d3f562eb..1e1a75a6e3974 100644 --- a/src/radostool.cc +++ b/src/radostool.cc @@ -23,9 +23,6 @@ #include -int aio_bench(Rados& rados, rados_pool_t pool, int concurrentios, int secondsToRun, - int writeSize, int readOffResults); - void usage() { cerr << "usage: radostool [options] [commands]" << std::endl; @@ -35,13 +32,163 @@ void usage() << " (osd|pg|mds) stat -- get monitor subsystem status" << std::endl << " ..." << std::endl; */ - cerr << "Options:" << std::endl; + cerr << "Commands:\n"; + cerr << " lspools -- list pools\n\n"; + + cerr << " get objname -- fetch object\n"; + cerr << " put objname -- write object\n"; + cerr << " ls -- list objects in pool\n\n"; + + cerr << " bench [-c concurrentwrites] [-b writesize] [verify] [sync]\n"; + cerr << " default is 16 concurrent IOs and 1 MB writes size\n\n"; + + cerr << "Options:\n"; cerr << " -i infile\n"; cerr << " -o outfile\n"; cerr << " specify input or output file (for certain commands)\n"; - generic_client_usage(); + exit(1); +} + + +/********************************************** + +**********************************************/ + +int aio_bench(Rados& rados, rados_pool_t pool, int secondsToRun, int concurrentios, + int writeSize, int readOffResults, int sync) { + + cout << "Maintaining " << concurrentios << " concurrent writes of " << writeSize + << " bytes for at least " << secondsToRun << " seconds." << std::endl; + + Rados::AioCompletion* completions[concurrentios]; + char* name[concurrentios]; + bufferlist* contents[concurrentios]; + char contentsChars[writeSize]; + double totalLatency = 0; + utime_t maxLatency; + utime_t startTimes[concurrentios]; + int writesMade = 0; + int writesCompleted = 0; + time_t initialTime; + utime_t startTime; + utime_t stopTime; + + time(&initialTime); + stringstream initialTimeS(""); + initialTimeS << initialTime; + const char* iTime = initialTimeS.str().c_str(); + maxLatency.set_from_double(0); + //set up writes so I can start them together + for (int i = 0; iappend(contentsChars, writeSize); + } + + //set up the pool, get start time, and go! + cout << "open pool result = " << rados.open_pool("data",&pool) << " pool = " << pool << std::endl; + + startTime = g_clock.now(); + + for (int i = 0; iappend(contentsChars, writeSize); + completions[slot]->wait_for_complete(); + currentLatency = g_clock.now() - startTimes[slot]; + totalLatency += currentLatency; + if( currentLatency > maxLatency) maxLatency = currentLatency; + ++writesCompleted; + completions[slot]->release(); + //write new stuff to rados, then delete old stuff + //and save locations of new stuff for later deletion + startTimes[slot] = g_clock.now(); + rados.aio_write(pool, newName, 0, *newContents, writeSize, &completions[slot]); + ++writesMade; + delete name[slot]; + delete contents[slot]; + name[slot] = newName; + contents[slot] = newContents; + } + + cerr << "Waiting for last writes to finish\n"; + while (writesCompleted < writesMade) { + slot = writesCompleted % concurrentios; + completions[slot]->wait_for_complete(); + currentLatency = g_clock.now() - startTimes[slot]; + totalLatency += currentLatency; + if (currentLatency > maxLatency) maxLatency = currentLatency; + completions[slot]-> release(); + ++writesCompleted; + delete name[slot]; + delete contents[slot]; + } + + utime_t timePassed = g_clock.now() - startTime; + + //check objects for consistency if requested + int errors = 0; + if (readOffResults) { + char matchName[128]; + object_t oid; + bufferlist actualContents; + for (int i = 0; i < writesCompleted; ++i ) { + snprintf(matchName, 128, "Object %s:%d", iTime, i); + oid = object_t(matchName); + snprintf(contentsChars, writeSize, "I'm the %dth object!", i); + rados.read(pool, oid, 0, actualContents, writeSize); + if (strcmp(contentsChars, actualContents.c_str()) != 0 ) { + cerr << "Object " << matchName << " is not correct!"; + ++errors; + } + actualContents.clear(); + } + } + + char bw[20]; + double bandwidth = ((double)writesCompleted)*((double)writeSize)/(double)timePassed; + bandwidth = bandwidth/(1024*1024); // we want it in MB/sec + sprintf(bw, "%.3lf \n", bandwidth); + + double averageLatency = totalLatency / writesCompleted; + + cout << "Total time run: " << timePassed << std::endl + << "Total writes made: " << writesCompleted << std::endl + << "Write size: " << writeSize << std::endl + << "Bandwidth (MB/sec): " << bw << std::endl + << "Average Latency: " << averageLatency << std::endl + << "Max latency: " << maxLatency << std::endl + << "Time waiting for Rados:" << totalLatency/concurrentios << std::endl; + + if (readOffResults) { + if (errors) cout << "WARNING: There were " << errors << " total errors in copying!\n"; + else cout << "No errors in copying!\n"; + } + return 0; } + int main(int argc, const char **argv) { DEFINE_CONF_VARS(usage); @@ -55,6 +202,10 @@ int main(int argc, const char **argv) const char *outfile = 0; const char *pool = 0; + + int concurrent_ios = 16; + int write_size = 1 << 20; + FOR_EACH_ARG(args) { if (CONF_ARG_EQ("out_file", 'o')) { @@ -73,6 +224,10 @@ int main(int argc, const char **argv) CONF_SAFE_SET_ARG_VAL(&pool, OPT_STR); } else if (CONF_ARG_EQ("help", 'h')) { usage(); + } else if (CONF_ARG_EQ("concurrent-ios", 'c')) { + CONF_SAFE_SET_ARG_VAL(&concurrent_ios, OPT_INT); + } else if (CONF_ARG_EQ("block-size", 'b')) { + CONF_SAFE_SET_ARG_VAL(&write_size, OPT_INT); } else if (args[i][0] == '-' && nargs.empty()) { cerr << "unrecognized option " << args[i] << std::endl; usage(); @@ -152,14 +307,20 @@ int main(int argc, const char **argv) } } else if (strcmp(nargs[0], "bench") == 0) { - if ( nargs.size() < 5) { - cerr << "bench requires 4 arguments: Concurrent writes," << std::endl - << "minimum seconds to run, write size, and consistency checking" << std::endl - << "(1 for yes, 0 for no)." << std::endl; - } - else { - aio_bench(rados, p, atoi(nargs[1]), atoi(nargs[2]), atoi(nargs[3]), atoi(nargs[4])); + if (nargs.size() < 2) + usage(); + int seconds = atoi(nargs[1]); + int sync = 0; + int verify = 0; + for (unsigned i=2; iappend(contentsChars, writeSize); - } - - //set up the pool, get start time, and go! - cout << "open pool result = " << rados.open_pool("data",&pool) << " pool = " << pool << std::endl; - - startTime = g_clock.now(); - - for (int i = 0; iappend(contentsChars, writeSize); - completions[slot]->wait_for_complete(); - currentLatency = g_clock.now() - startTimes[slot]; - totalLatency += currentLatency; - if( currentLatency > maxLatency) maxLatency = currentLatency; - ++writesCompleted; - completions[slot]->release(); - //write new stuff to rados, then delete old stuff - //and save locations of new stuff for later deletion - startTimes[slot] = g_clock.now(); - rados.aio_write(pool, newName, 0, *newContents, writeSize, &completions[slot]); - ++writesMade; - delete name[slot]; - delete contents[slot]; - name[slot] = newName; - contents[slot] = newContents; - } - - cerr << "Waiting for last writes to finish\n"; - while (writesCompleted < writesMade) { - slot = writesCompleted % concurrentios; - completions[slot]->wait_for_complete(); - currentLatency = g_clock.now() - startTimes[slot]; - totalLatency += currentLatency; - if (currentLatency > maxLatency) maxLatency = currentLatency; - completions[slot]-> release(); - ++writesCompleted; - delete name[slot]; - delete contents[slot]; - } - - utime_t timePassed = g_clock.now() - startTime; - - //check objects for consistency if requested - int errors = 0; - if (readOffResults) { - char matchName[128]; - object_t oid; - bufferlist actualContents; - for (int i = 0; i < writesCompleted; ++i ) { - snprintf(matchName, 128, "Object %s:%d", iTime, i); - oid = object_t(matchName); - snprintf(contentsChars, writeSize, "I'm the %dth object!", i); - rados.read(pool, oid, 0, actualContents, writeSize); - if (strcmp(contentsChars, actualContents.c_str()) != 0 ) { - cerr << "Object " << matchName << " is not correct!"; - ++errors; - } - actualContents.clear(); - } - } - - char bw[20]; - double bandwidth = ((double)writesCompleted)*((double)writeSize)/(double)timePassed; - bandwidth = bandwidth/(1024*1024); // we want it in MB/sec - sprintf(bw, "%.3lf \n", bandwidth); - - double averageLatency = totalLatency / writesCompleted; - - cout << "Total time run: " << timePassed << std::endl - << "Total writes made: " << writesCompleted << std::endl - << "Write size: " << writeSize << std::endl - << "Bandwidth (MB/sec): " << bw << std::endl - << "Average Latency: " << averageLatency << std::endl - << "Max latency: " << maxLatency << std::endl - << "Time waiting for Rados:" << totalLatency/concurrentios << std::endl; - - if (readOffResults) { - if (errors) cout << "WARNING: There were " << errors << " total errors in copying!\n"; - else cout << "No errors in copying!\n"; - } - return 0; -} -- 2.39.5