You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2012/10/09 14:52:14 UTC
svn commit: r1396006 - in /hbase/branches/0.89-fb: conf/
src/main/java/org/apache/hadoop/hbase/util/
src/test/java/org/apache/hadoop/hbase/benchmarks/
src/test/java/org/apache/hadoop/hbase/util/
Author: mbautin
Date: Tue Oct 9 12:52:13 2012
New Revision: 1396006
URL: http://svn.apache.org/viewvc?rev=1396006&view=rev
Log:
[HBASE-6923] Create scanner benchmark
Author: kranganathan
Summary: This diff creates a generic benchmarking framework and implements a scan benchmark from memory for HBase
Test Plan:
Tested by running benchmark by running:
bin/hbase org.apache.hadoop.hbase.benchmarks.ScanBenchmark
Reviewers: kannan, aaiyer, liyintang
Reviewed By: kannan
CC: hbase-eng@
Differential Revision: https://phabricator.fb.com/D594846
Added:
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/Benchmark.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/BenchmarkResults.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/ScanBenchmark.java
Modified:
hbase/branches/0.89-fb/conf/hbase-env.sh
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestKVGenerator.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java
Modified: hbase/branches/0.89-fb/conf/hbase-env.sh
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/conf/hbase-env.sh?rev=1396006&r1=1396005&r2=1396006&view=diff
==============================================================================
--- hbase/branches/0.89-fb/conf/hbase-env.sh (original)
+++ hbase/branches/0.89-fb/conf/hbase-env.sh Tue Oct 9 12:52:13 2012
@@ -23,6 +23,7 @@
# The java implementation to use. Java 1.6 required.
# export JAVA_HOME=/usr/java/jdk1.6.0/
+export JAVA_HOME=/usr/local/jdk-6u14-64
# Extra Java CLASSPATH elements. Optional.
# export HBASE_CLASSPATH=
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java?rev=1396006&r1=1396005&r2=1396006&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/AbstractHBaseTool.java Tue Oct 9 12:52:13 2012
@@ -167,7 +167,7 @@ public abstract class AbstractHBaseTool
}
/** Call this from the concrete tool class's main function. */
- protected void doStaticMain(String args[]) {
+ protected int doStaticMain(String args[]) {
int ret;
try {
ret = ToolRunner.run(HBaseConfiguration.create(), this, args);
@@ -175,7 +175,7 @@ public abstract class AbstractHBaseTool
LOG.error("Error running command-line tool", ex);
ret = EXIT_FAILURE;
}
- System.exit(ret);
+ return ret;
}
}
Added: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/Benchmark.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/Benchmark.java?rev=1396006&view=auto
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/Benchmark.java (added)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/Benchmark.java Tue Oct 9 12:52:13 2012
@@ -0,0 +1,127 @@
+package org.apache.hadoop.hbase.benchmarks;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.loadtest.ColumnFamilyProperties;
+import org.apache.hadoop.hbase.loadtest.HBaseUtils;
+import org.apache.hadoop.hbase.util.LoadTestTool;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+public abstract class Benchmark {
+ public static final Log LOG = LogFactory.getLog(Benchmark.class);
+ public static final String ARG_ZOOKEEPER = "--zookeeper";
+ // use local zookeeper by default
+ public String zkNodeName = null;
+ // cached config object
+ public Configuration conf;
+ // benchmark results abstraction
+ public BenchmarkResults benchmarkResults;
+
+ /**
+ * Initialize the benchmark results structure "benchmarkResults"
+ */
+ public abstract void initBenchmarkResults();
+
+ /**
+ * Run the actual benchmark
+ * @throws Throwable
+ */
+ public abstract void runBenchmark() throws Throwable;
+
+ /**
+ * Parse the args to the benchmark
+ * @param args
+ */
+ public void parseArgs(String[] args) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].equals(ARG_ZOOKEEPER)) {
+ zkNodeName = args[i+1];
+ i++;
+ }
+ }
+ }
+
+ public void initialize() {
+ conf = HBaseConfiguration.create();
+ if (zkNodeName != null) {
+ conf.set("hbase.zookeeper.quorum", zkNodeName);
+ conf.setInt("hbase.zookeeper.property.clientPort", 2181);
+ }
+ }
+
+ public void printBenchmarkResults() {
+ System.out.println("Benchmark results");
+ benchmarkResults.prettyPrint();
+ }
+
+ /**
+ * Helper function to create a table and load the requested number of KVs
+ * into the table - if the table does not exist. If the table exists, then
+ * nothing is done.
+ * @throws IOException
+ */
+ public HTable createTableAndLoadData(byte[] tableName, int kvSize,
+ long numKVs) throws IOException {
+ HTable htable = null;
+ try {
+ htable = new HTable(conf, tableName);
+ } catch (IOException e) {
+ LOG.info("Table " + new String(tableName) + " already exists.");
+ }
+
+ if (htable != null) return htable;
+
+ ColumnFamilyProperties familyProperty = new ColumnFamilyProperties();
+ familyProperty.familyName = "cf1";
+ familyProperty.minColsPerKey = 1;
+ familyProperty.maxColsPerKey = 1;
+ familyProperty.minColDataSize = kvSize;
+ familyProperty.maxColDataSize = kvSize;
+ familyProperty.maxVersions = 1;
+ familyProperty.compressionType = "none";
+
+ ColumnFamilyProperties[] familyProperties = new ColumnFamilyProperties[1];
+ familyProperties[0] = familyProperty;
+
+ // create the table
+ HBaseUtils.createTableIfNotExists(conf, tableName, familyProperties, 1);
+ // write data if the table was created
+ LOG.info("Loading data for the table");
+ String[] loadTestToolArgs = {
+ "-zk", "localhost",
+ "-tn", "bench.ScanFromMemoryPerf",
+ "-cf", familyProperty.familyName,
+ "-write", "1:50",
+ "-num_keys", "" + numKVs,
+ "-multiput",
+ "-compression", "NONE",
+ };
+ LoadTestTool.doMain(loadTestToolArgs);
+ LOG.info("Done loading data");
+
+ htable = new HTable(conf, tableName);
+ return htable;
+ }
+
+ public static void benchmarkRunner(
+ Class<? extends Benchmark> benchmarkClass, String[] args)
+ throws Throwable {
+ // suppress unnecessary logging
+ Logger.getLogger("org.apache.zookeeper").setLevel(Level.ERROR);
+ Logger.getLogger("org.apache.hadoop.hbase.client").setLevel(Level.ERROR);
+ Logger.getLogger("org.apache.hadoop.hbase.zookeeper").setLevel(Level.ERROR);
+
+ Benchmark benchmark = benchmarkClass.newInstance();
+ benchmark.parseArgs(args);
+ benchmark.initialize();
+ benchmark.initBenchmarkResults();
+ benchmark.runBenchmark();
+ benchmark.printBenchmarkResults();
+ }
+}
Added: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/BenchmarkResults.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/BenchmarkResults.java?rev=1396006&view=auto
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/BenchmarkResults.java (added)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/BenchmarkResults.java Tue Oct 9 12:52:13 2012
@@ -0,0 +1,71 @@
+package org.apache.hadoop.hbase.benchmarks;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * General purpose utility class that tracks the results of a benchmark
+ * experiment. Abstracts the X-axis and Y-axis of the table, and the
+ * result object.
+ *
+ * @param <DimensionX> X axis of the result
+ * @param <DimensionY> Y axis of the result
+ * @param <Result> Result object
+ */
+public class BenchmarkResults<DimensionX, DimensionY, Result> {
+ String xFormat;
+ String resultFormat;
+ DimensionX[] xValues;
+ DimensionY[] yValues;
+ List<String> headerEntries;
+ private Map<DimensionX, Map<DimensionY, Result>> results =
+ new HashMap<DimensionX, Map<DimensionY, Result>>();
+
+ public BenchmarkResults(DimensionX[] xValues, DimensionY[] yValues,
+ String xFormat, String resultFormat, List<String> headerEntries) {
+ this.xValues = xValues;
+ this.yValues = yValues;
+ this.xFormat = xFormat;
+ this.resultFormat = resultFormat;
+ this.headerEntries = headerEntries;
+ }
+
+ /**
+ * Add a single result entry
+ * @param xValue
+ * @param yValue
+ * @param result
+ */
+ public void addResult(DimensionX xValue, DimensionY yValue, Result result) {
+ Map<DimensionY, Result> yValue_to_result_map = results.get(xValue);
+ if (yValue_to_result_map == null) {
+ yValue_to_result_map = new HashMap<DimensionY, Result>();
+ }
+ yValue_to_result_map.put(yValue, result);
+ results.put(xValue, yValue_to_result_map);
+ }
+
+ /**
+ * Pretty print the results to STDOUT
+ */
+ public void prettyPrint() {
+ // print the headers
+ for (String s : headerEntries) {
+ System.out.printf("%s\t", s);
+ }
+ System.out.println("");
+ // print all the values in the results
+ for (DimensionX x : xValues) {
+ System.out.printf(xFormat, x);
+ Map<DimensionY, Result> yValue_to_result_map = results.get(x);
+ for (DimensionY y : yValues) {
+ System.out.printf("\t" + resultFormat, yValue_to_result_map.get(y));
+ }
+ // row done
+ System.out.println("");
+ }
+ // done with the results
+ System.out.println("\n");
+ }
+}
Added: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/ScanBenchmark.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/ScanBenchmark.java?rev=1396006&view=auto
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/ScanBenchmark.java (added)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/benchmarks/ScanBenchmark.java Tue Oct 9 12:52:13 2012
@@ -0,0 +1,128 @@
+package org.apache.hadoop.hbase.benchmarks;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.TableExistsException;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.loadtest.ColumnFamilyProperties;
+import org.apache.hadoop.hbase.loadtest.HBaseUtils;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.LoadTestTool;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+/**
+ * This test compares the performance of scan when all the data is in memory
+ * (in the block cache). The setCaching parameter is varied and the read
+ * throughput is printed for various values of setCaching.
+ */
+public class ScanBenchmark extends Benchmark {
+ public static final Log LOG = LogFactory.getLog(ScanBenchmark.class);
+ private static final long PRINT_INTERVAL_KVS = 1000000;
+ private byte[] tableName = Bytes.toBytes("bench.ScanFromMemoryPerf");
+ private static Integer[] SET_CACHING_VALUES = {
+// 1000, 2000, 3000, 4000,
+// 5000, 6000, 7000, 8000,
+ 9000, 10000, 11000, 12000,
+ 13000, 14000,
+ };
+ private static Integer[] SET_PREFETCH_VALUES = { 0 };
+
+ public void initBenchmarkResults() {
+ List<String> header = new ArrayList<String>();
+ header.add("caching");
+ for (int i = 0; i < SET_PREFETCH_VALUES.length; i++) {
+ header.add("prefetch=" + SET_PREFETCH_VALUES[i]);
+ }
+ benchmarkResults = new BenchmarkResults<Integer, Integer, Double>(
+ SET_CACHING_VALUES, SET_PREFETCH_VALUES, " %5d", " %3.2f", header);
+ }
+
+ public void runBenchmark() throws Throwable {
+ // populate the table
+ createTableAndLoadData(tableName, 50, 1000000);
+ // warm block cache
+ runExperiment(false, 10000, 0);
+ for (int caching : SET_CACHING_VALUES) {
+ for (int prefetch : SET_PREFETCH_VALUES) {
+ try {
+ runExperiment(true, caching, prefetch);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void runExperiment(boolean printStats, int caching, int prefetch) throws IOException {
+ Configuration conf = HBaseConfiguration.create();
+ HTable htable = HBaseUtils.getHTable(conf, tableName);
+
+ // create the scan object with the right params
+ Scan scan = new Scan();
+ scan.setMaxVersions(1);
+ // set caching
+ scan.setCaching(caching);
+
+ long numKVs = 0;
+ long numBytes = 0;
+ Result kv;
+ long printAfterNumKVs = PRINT_INTERVAL_KVS;
+ long startTime = System.currentTimeMillis();
+
+ // read all the KV's
+ ResultScanner scanner = htable.getScanner(scan);
+ while ( (kv = scanner.next()) != null) {
+ numKVs += kv.size();
+ if (kv.raw() != null) {
+ for (KeyValue k : kv.raw())
+ numBytes += k.getLength();
+ }
+
+ if (numKVs > printAfterNumKVs) {
+ printAfterNumKVs += PRINT_INTERVAL_KVS;
+ if (printStats) printStats(numKVs, numBytes, startTime, caching, prefetch);
+ }
+ }
+
+ if (printStats) printStats(numKVs, numBytes, startTime, caching, prefetch);
+ scanner.close();
+ }
+
+ private void printStats(long numKVs, long numBytes, long startTime,
+ int caching, int prefetch) {
+ long t2 = System.currentTimeMillis();
+ double numBytesInMB = numBytes * 1.0 / (1024 * 1024);
+ double rate = numBytesInMB * (1000 * 1.0 / (t2 - startTime));
+ System.out.println("Scan: caching = " + caching +
+ ", prefetch = " + prefetch +
+ ", kvs = " + numKVs +
+ ", bytes = " + String.format("%1$,.2f", numBytesInMB) + " MB" +
+ ", time = " + (t2 - startTime) + " ms" +
+ ", rate = " + String.format("%1$,.2f", rate) + "MB/s"
+ );
+ benchmarkResults.addResult(caching, prefetch, rate);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ String className =
+ Thread.currentThread().getStackTrace()[1].getClassName();
+ System.out.println("Running benchmark " + className);
+ @SuppressWarnings("unchecked")
+ Class<? extends Benchmark> benchmarkClass =
+ (Class<? extends Benchmark>)Class.forName(className);
+ Benchmark.benchmarkRunner(benchmarkClass, args);
+ }
+}
\ No newline at end of file
Modified: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestKVGenerator.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestKVGenerator.java?rev=1396006&r1=1396005&r2=1396006&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestKVGenerator.java (original)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestKVGenerator.java Tue Oct 9 12:52:13 2012
@@ -65,10 +65,11 @@ public class LoadTestKVGenerator {
*/
public static String md5PrefixedKey(long key) {
String stringKey = Long.toString(key);
- String md5hash = MD5Hash.getMD5AsHex(Bytes.toBytes(stringKey));
-
+ // use a 4 byte md5 hash prefix (gives 65K regions)
+ String md5hash =
+ MD5Hash.getMD5AsHex(Bytes.toBytes(stringKey)).substring(0, 4);
// flip the key to randomize
- return md5hash + "-" + stringKey;
+ return md5hash + ":" + stringKey;
}
/**
@@ -80,8 +81,11 @@ public class LoadTestKVGenerator {
*/
public byte[] generateRandomSizeValue(long key, String qual) {
String rowKey = md5PrefixedKey(key);
- int dataSize = minValueSize + randomForValueSize.nextInt(
+ int dataSize = minValueSize;
+ if (minValueSize != maxValueSize) {
+ dataSize += randomForValueSize.nextInt(
Math.abs(maxValueSize - minValueSize));
+ }
return getValueForRowColumn(rowKey, qual, dataSize);
}
Modified: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java?rev=1396006&r1=1396005&r2=1396006&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java (original)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/LoadTestTool.java Tue Oct 9 12:52:13 2012
@@ -43,15 +43,15 @@ public class LoadTestTool extends Abstra
/** Table name for the test */
private byte[] tableName;
+
+ /** cf name for the test */
+ private byte[] columnFamily;
/** Table name to use of not overridden on the command line */
private static final String DEFAULT_TABLE_NAME = "cluster_test";
- /** Column family used by the test */
- static byte[] COLUMN_FAMILY = Bytes.toBytes("test_cf");
-
- /** Column families used by the test */
- static final byte[][] COLUMN_FAMILIES = { COLUMN_FAMILY };
+ /** Default column family used by the test */
+ private static String DEFAULT_CF_NAME = "test_cf";
/** The number of reader/writer threads if not specified */
private static final int DEFAULT_NUM_THREADS = 20;
@@ -96,12 +96,16 @@ public class LoadTestTool extends Abstra
private static final String OPT_READ = "read";
private static final String OPT_START_KEY = "start_key";
private static final String OPT_TABLE_NAME = "tn";
+ private static final String OPT_CF_NAME = "cf";
private static final String OPT_ZK_QUORUM = "zk";
private static final String OPT_PROFILING = "profiling";
private static final String OPT_RPC_COMPRESSION = "rpc_compression";
private static final long DEFAULT_START_KEY = 0;
+ /** Column families used by the test */
+ private byte[][] COLUMN_FAMILIES;
+
/** This will be removed as we factor out the dependency on command line */
private CommandLine cmd;
@@ -134,7 +138,12 @@ public class LoadTestTool extends Abstra
private int maxReadErrors = MultiThreadedReader.DEFAULT_MAX_ERRORS;
private int verifyPercent;
private int profilePercent = 0;
-
+
+ public LoadTestTool() {
+ if (columnFamily == null) columnFamily = Bytes.toBytes(DEFAULT_CF_NAME);
+ COLUMN_FAMILIES = new byte[][] { columnFamily };
+ }
+
private boolean isBatched;
private int batchSize;
@@ -202,6 +211,7 @@ public class LoadTestTool extends Abstra
addOptWithArg(OPT_ZK_QUORUM, "ZK quorum as comma-separated host names " +
"without port numbers");
addOptWithArg(OPT_TABLE_NAME, "The name of the table to read or write");
+ addOptWithArg(OPT_CF_NAME, "The column family to read or write");
addOptWithArg(OPT_WRITE, OPT_USAGE_LOAD);
addOptWithArg(OPT_BATCHED_WRITES, "Use batched writes (with WAL)");
addOptWithArg(OPT_BATCHED_WRITES_CNT, "Size of a batch (if using batched writes)");
@@ -236,6 +246,8 @@ public class LoadTestTool extends Abstra
tableName = Bytes.toBytes(cmd.getOptionValue(OPT_TABLE_NAME,
DEFAULT_TABLE_NAME));
+ columnFamily = Bytes.toBytes(cmd.getOptionValue(OPT_CF_NAME,
+ DEFAULT_CF_NAME));
startKey = parseLong(cmd.getOptionValue(OPT_START_KEY,
String.valueOf(DEFAULT_START_KEY)), 0, Long.MAX_VALUE);
long numKeys = parseLong(cmd.getOptionValue(OPT_NUM_KEYS), 1,
@@ -353,11 +365,11 @@ public class LoadTestTool extends Abstra
}
HBaseTestingUtility.createPreSplitLoadTestTable(conf, tableName,
- COLUMN_FAMILY, compressAlgo, dataBlockEncodingAlgo);
+ columnFamily, compressAlgo, dataBlockEncodingAlgo);
applyColumnFamilyOptions(tableName, COLUMN_FAMILIES);
if (isWrite) {
- writerThreads = new MultiThreadedWriter(conf, tableName, COLUMN_FAMILY,
+ writerThreads = new MultiThreadedWriter(conf, tableName, columnFamily,
profilePercent, this.txCompression, this.rxCompression);
writerThreads.setMultiPut(isMultiPut);
writerThreads.setBatching(isBatched);
@@ -367,7 +379,7 @@ public class LoadTestTool extends Abstra
}
if (isRead) {
- readerThreads = new MultiThreadedReader(conf, tableName, COLUMN_FAMILY,
+ readerThreads = new MultiThreadedReader(conf, tableName, columnFamily,
verifyPercent, profilePercent, this.txCompression, this.rxCompression);
readerThreads.setMaxErrors(maxReadErrors);
readerThreads.setKeyWindow(keyWindow);
@@ -397,9 +409,14 @@ public class LoadTestTool extends Abstra
readerThreads.waitForFinish();
}
}
+
+ public static int doMain(String[] args) {
+ return new LoadTestTool().doStaticMain(args);
+ }
public static void main(String[] args) {
- new LoadTestTool().doStaticMain(args);
+ int ret = doMain(args);
+ System.exit(ret);
}
}