View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import static org.apache.hadoop.hbase.regionserver.HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY;
22  import static org.apache.hadoop.hbase.regionserver.HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY;
23  import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_SIZE_KEY;
24  import static org.apache.hadoop.hbase.regionserver.HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY;
25  import static org.apache.hadoop.hbase.regionserver.HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY;
26  
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.io.util.HeapMemorySizeUtil;
31  import org.apache.hadoop.hbase.regionserver.HeapMemoryManager.TunerContext;
32  import org.apache.hadoop.hbase.regionserver.HeapMemoryManager.TunerResult;
33  
34  /**
35   * The default implementation for the HeapMemoryTuner. This will do simple checks to decide
36   * whether there should be changes in the heap size of memstore/block cache. When there is no block
37   * cache eviction at all but there are flushes because of global heap pressure, it will increase the
38   * memstore heap size and decrease block cache size. The step value for this heap size change can be
39   * specified using the config <i>hbase.regionserver.heapmemory.autotuner.step</i>. When there is no
40   * memstore flushes because of heap pressure but there is block cache evictions it will increase the
41   * block cache heap.
42   */
43  @InterfaceAudience.Private
44  class DefaultHeapMemoryTuner implements HeapMemoryTuner {
45  
46    public static final String STEP_KEY = "hbase.regionserver.heapmemory.autotuner.step";
47    public static final float DEFAULT_STEP_VALUE = 0.02f; // 2%
48  
49    private static final TunerResult TUNER_RESULT = new TunerResult(true);
50    private static final TunerResult NO_OP_TUNER_RESULT = new TunerResult(false);
51  
52    private Configuration conf;
53    private float step = DEFAULT_STEP_VALUE;
54  
55    private float globalMemStorePercentMinRange;
56    private float globalMemStorePercentMaxRange;
57    private float blockCachePercentMinRange;
58    private float blockCachePercentMaxRange;
59  
60    @Override
61    public TunerResult tune(TunerContext context) {
62      long blockedFlushCount = context.getBlockedFlushCount();
63      long unblockedFlushCount = context.getUnblockedFlushCount();
64      long evictCount = context.getEvictCount();
65      boolean memstoreSufficient = blockedFlushCount == 0 && unblockedFlushCount == 0;
66      boolean blockCacheSufficient = evictCount == 0;
67      if (memstoreSufficient && blockCacheSufficient) {
68        return NO_OP_TUNER_RESULT;
69      }
70      float newMemstoreSize;
71      float newBlockCacheSize;
72      if (memstoreSufficient) {
73        // Increase the block cache size and corresponding decrease in memstore size
74        newBlockCacheSize = context.getCurBlockCacheSize() + step;
75        newMemstoreSize = context.getCurMemStoreSize() - step;
76      } else if (blockCacheSufficient) {
77        // Increase the memstore size and corresponding decrease in block cache size
78        newBlockCacheSize = context.getCurBlockCacheSize() - step;
79        newMemstoreSize = context.getCurMemStoreSize() + step;
80      } else {
81        return NO_OP_TUNER_RESULT;
82        // As of now not making any tuning in write/read heavy scenario.
83      }
84      if (newMemstoreSize > globalMemStorePercentMaxRange) {
85        newMemstoreSize = globalMemStorePercentMaxRange;
86      } else if (newMemstoreSize < globalMemStorePercentMinRange) {
87        newMemstoreSize = globalMemStorePercentMinRange;
88      }
89      if (newBlockCacheSize > blockCachePercentMaxRange) {
90        newBlockCacheSize = blockCachePercentMaxRange;
91      } else if (newBlockCacheSize < blockCachePercentMinRange) {
92        newBlockCacheSize = blockCachePercentMinRange;
93      }
94      TUNER_RESULT.setBlockCacheSize(newBlockCacheSize);
95      TUNER_RESULT.setMemstoreSize(newMemstoreSize);
96      return TUNER_RESULT;
97    }
98  
99    @Override
100   public Configuration getConf() {
101     return this.conf;
102   }
103 
104   @Override
105   public void setConf(Configuration conf) {
106     this.conf = conf;
107     this.step = conf.getFloat(STEP_KEY, DEFAULT_STEP_VALUE);
108     this.blockCachePercentMinRange = conf.getFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY,
109         conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT));
110     this.blockCachePercentMaxRange = conf.getFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY,
111         conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT));
112     this.globalMemStorePercentMinRange = conf.getFloat(MEMSTORE_SIZE_MIN_RANGE_KEY,
113         HeapMemorySizeUtil.getGlobalMemStorePercent(conf, false));
114     this.globalMemStorePercentMaxRange = conf.getFloat(MEMSTORE_SIZE_MAX_RANGE_KEY,
115         HeapMemorySizeUtil.getGlobalMemStorePercent(conf, false));
116   }
117 }