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.classification.InterfaceAudience;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.regionserver.HeapMemoryManager.TunerContext;
31  import org.apache.hadoop.hbase.regionserver.HeapMemoryManager.TunerResult;
32  
33  /**
34   * The default implementation for the HeapMemoryTuner. This will do simple checks to decide
35   * whether there should be changes in the heap size of memstore/block cache. When there is no block
36   * cache eviction at all but there are flushes because of global heap pressure, it will increase the
37   * memstore heap size and decrease block cache size. The step value for this heap size change can be
38   * specified using the config <i>hbase.regionserver.heapmemory.autotuner.step</i>. When there is no
39   * memstore flushes because of heap pressure but there is block cache evictions it will increase the
40   * block cache heap.
41   */
42  @InterfaceAudience.Private
43  class DefaultHeapMemoryTuner implements HeapMemoryTuner {
44  
45    public static final String STEP_KEY = "hbase.regionserver.heapmemory.autotuner.step";
46    public static final float DEFAULT_STEP_VALUE = 0.02f; // 2%
47  
48    private static final TunerResult TUNER_RESULT = new TunerResult(true);
49    private static final TunerResult NO_OP_TUNER_RESULT = new TunerResult(false);
50  
51    private Configuration conf;
52    private float step = DEFAULT_STEP_VALUE;
53  
54    private float globalMemStorePercentMinRange;
55    private float globalMemStorePercentMaxRange;
56    private float blockCachePercentMinRange;
57    private float blockCachePercentMaxRange;
58  
59    @Override
60    public TunerResult tune(TunerContext context) {
61      long blockedFlushCount = context.getBlockedFlushCount();
62      long unblockedFlushCount = context.getUnblockedFlushCount();
63      long evictCount = context.getEvictCount();
64      boolean memstoreSufficient = blockedFlushCount == 0 && unblockedFlushCount == 0;
65      boolean blockCacheSufficient = evictCount == 0;
66      if (memstoreSufficient && blockCacheSufficient) {
67        return NO_OP_TUNER_RESULT;
68      }
69      float newMemstoreSize;
70      float newBlockCacheSize;
71      if (memstoreSufficient) {
72        // Increase the block cache size and corresponding decrease in memstore size
73        newBlockCacheSize = context.getCurBlockCacheSize() + step;
74        newMemstoreSize = context.getCurMemStoreSize() - step;
75      } else if (blockCacheSufficient) {
76        // Increase the memstore size and corresponding decrease in block cache size
77        newBlockCacheSize = context.getCurBlockCacheSize() - step;
78        newMemstoreSize = context.getCurMemStoreSize() + step;
79      } else {
80        return NO_OP_TUNER_RESULT;
81        // As of now not making any tuning in write/read heavy scenario.
82      }
83      if (newMemstoreSize > globalMemStorePercentMaxRange) {
84        newMemstoreSize = globalMemStorePercentMaxRange;
85      } else if (newMemstoreSize < globalMemStorePercentMinRange) {
86        newMemstoreSize = globalMemStorePercentMinRange;
87      }
88      if (newBlockCacheSize > blockCachePercentMaxRange) {
89        newBlockCacheSize = blockCachePercentMaxRange;
90      } else if (newBlockCacheSize < blockCachePercentMinRange) {
91        newBlockCacheSize = blockCachePercentMinRange;
92      }
93      TUNER_RESULT.setBlockCacheSize(newBlockCacheSize);
94      TUNER_RESULT.setMemstoreSize(newMemstoreSize);
95      return TUNER_RESULT;
96    }
97  
98    @Override
99    public Configuration getConf() {
100     return this.conf;
101   }
102 
103   @Override
104   public void setConf(Configuration conf) {
105     this.conf = conf;
106     this.step = conf.getFloat(STEP_KEY, DEFAULT_STEP_VALUE);
107     this.blockCachePercentMinRange = conf.getFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY,
108         conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT));
109     this.blockCachePercentMaxRange = conf.getFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY,
110         conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT));
111     this.globalMemStorePercentMinRange = conf.getFloat(MEMSTORE_SIZE_MIN_RANGE_KEY,
112         MemStoreFlusher.getGlobalMemStorePercent(conf));
113     this.globalMemStorePercentMaxRange = conf.getFloat(MEMSTORE_SIZE_MAX_RANGE_KEY,
114         MemStoreFlusher.getGlobalMemStorePercent(conf));
115   }
116 }