View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase;
19  
20  import java.io.IOException;
21  import java.util.HashSet;
22  import java.util.Set;
23  import java.util.concurrent.ExecutorService;
24  import java.util.concurrent.Executors;
25  import java.util.concurrent.Future;
26  import java.util.concurrent.TimeUnit;
27  import java.util.concurrent.atomic.AtomicInteger;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.hadoop.conf.Configuration;
32  // import org.apache.hadoop.hbase.client.ConnectionFactory;
33  import org.apache.hadoop.hbase.client.HTable;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.apache.hadoop.util.Tool;
36  import org.apache.hadoop.util.ToolRunner;
37  
38  import com.yammer.metrics.Metrics;
39  import com.yammer.metrics.core.MetricName;
40  import com.yammer.metrics.core.Timer;
41  import com.yammer.metrics.core.TimerContext;
42  import com.yammer.metrics.stats.Snapshot;
43  
44  /**
45   * Simple Increments Performance Test. Run this from main. It is to go against a cluster.
46   * Presumption is the table exists already. Defaults are a zk ensemble of localhost:2181,
47   * a tableName of 'tableName', a column famly name of 'columnFamilyName', with 80 threads by
48   * default and 10000 increments per thread. To change any of these configs, pass -DNAME=VALUE as
49   * in -DtableName="newTableName". It prints out configuration it is running with at the start and
50   * on the end it prints out percentiles.
51   */
52  public class IncrementPerformanceTest implements Tool {
53    private static final Log LOG = LogFactory.getLog(IncrementPerformanceTest.class);
54    private static final byte [] QUALIFIER = new byte [] {'q'};
55    private Configuration conf;
56    private final MetricName metricName = new MetricName(this.getClass(), "increment");
57    private static final String TABLENAME = "tableName";
58    private static final String COLUMN_FAMILY = "columnFamilyName";
59    private static final String THREAD_COUNT = "threadCount";
60    private static final int DEFAULT_THREAD_COUNT = 80;
61    private static final String INCREMENT_COUNT = "incrementCount";
62    private static final int DEFAULT_INCREMENT_COUNT = 10000;
63  
64    IncrementPerformanceTest() {}
65  
66    public int run(final String [] args) throws Exception {
67      Configuration conf = getConf();
68      final TableName tableName = TableName.valueOf(conf.get(TABLENAME), TABLENAME);
69      final byte [] columnFamilyName = Bytes.toBytes(conf.get(COLUMN_FAMILY, COLUMN_FAMILY));
70      int threadCount = conf.getInt(THREAD_COUNT, DEFAULT_THREAD_COUNT);
71      final int incrementCount = conf.getInt(INCREMENT_COUNT, DEFAULT_INCREMENT_COUNT);
72      LOG.info("Running test with " + HConstants.ZOOKEEPER_QUORUM + "=" +
73        getConf().get(HConstants.ZOOKEEPER_QUORUM) + ", tableName=" + tableName +
74        ", columnFamilyName=" + columnFamilyName + ", threadCount=" + threadCount +
75        ", incrementCount=" + incrementCount);
76  
77      ExecutorService service = Executors.newFixedThreadPool(threadCount);
78      Set<Future<?>> futures = new HashSet<Future<?>>();
79      final AtomicInteger integer = new AtomicInteger(0); // needed a simple "final" counter
80      while (integer.incrementAndGet() <= threadCount) {
81        futures.add(service.submit(new Runnable() {
82          @Override
83          public void run() {
84            HTable table;
85            try {
86              // ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(TABLE_NAME));
87              table = new HTable(getConf(), tableName.getName());
88            } catch (Exception e) {
89              throw new RuntimeException(e);
90            }
91            Timer timer = Metrics.newTimer(metricName, TimeUnit.MILLISECONDS, TimeUnit.SECONDS);
92            for (int i = 0; i < incrementCount; i++) {
93              byte[] row = Bytes.toBytes(i);
94              TimerContext context = timer.time();
95              try {
96                table.incrementColumnValue(row, columnFamilyName, QUALIFIER, 1l);
97              } catch (IOException e) {
98                // swallow..it's a test.
99              } finally {
100               context.stop();
101             }
102           }
103         }
104       }));
105     }
106 
107     for(Future<?> future : futures) future.get();
108     service.shutdown();
109     Snapshot s = Metrics.newTimer(this.metricName,
110         TimeUnit.MILLISECONDS, TimeUnit.SECONDS).getSnapshot();
111     LOG.info(String.format("75th=%s, 95th=%s, 99th=%s", s.get75thPercentile(),
112         s.get95thPercentile(), s.get99thPercentile()));
113     return 0;
114   }
115 
116   @Override
117   public Configuration getConf() {
118     return this.conf;
119   }
120 
121   @Override
122   public void setConf(Configuration conf) {
123     this.conf = conf;
124   }
125 
126   public static void main(String[] args) throws Exception {
127     System.exit(ToolRunner.run(HBaseConfiguration.create(), new IncrementPerformanceTest(), args));
128   }
129 }