Skip to content

Commit c1bdeb8

Browse files
committed
HBASE-28600 Introduce hfile.block.cache.memory.size configuration
1 parent b20c42c commit c1bdeb8

File tree

5 files changed

+80
-26
lines changed

5 files changed

+80
-26
lines changed

hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,11 @@ public enum OperationStatusCode {
10601060

10611061
public static final float HFILE_BLOCK_CACHE_SIZE_DEFAULT = 0.4f;
10621062

1063+
/**
1064+
* Configuration key for the memory size of the block cache
1065+
*/
1066+
public static final String HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY = "hfile.block.cache.memory.size";
1067+
10631068
/**
10641069
* Configuration key for setting the fix size of the block size, default do nothing and it should
10651070
* be explicitly set by user or only used within ClientSideRegionScanner. if it's set less than

hbase-common/src/main/resources/hbase-default.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,14 @@ possible configurations would overwhelm and obscure the important.
10001000
Set to 0 to disable but it's not recommended; you need at least
10011001
enough cache to hold the storefile indices.</description>
10021002
</property>
1003+
<property>
1004+
<name>hfile.block.cache.memory.size</name>
1005+
<value></value>
1006+
<description>Defines the maximum heap memory allocated for the HFile block cache,
1007+
specified in bytes or human-readable formats like '10m' for megabytes or '10g' for gigabytes.
1008+
This configuration allows setting an absolute memory size instead of a percentage of the maximum heap.
1009+
Takes precedence over hfile.block.cache.size if both are specified.</description>
1010+
</property>
10031011
<property>
10041012
<name>hfile.block.index.cacheonwrite</name>
10051013
<value>false</value>

hbase-server/src/main/java/org/apache/hadoop/hbase/io/util/MemorySizeUtil.java

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.lang.management.MemoryUsage;
2323
import org.apache.hadoop.conf.Configuration;
2424
import org.apache.hadoop.hbase.HConstants;
25+
import org.apache.hadoop.hbase.StorageSize;
26+
import org.apache.hadoop.hbase.StorageUnit;
2527
import org.apache.hadoop.hbase.regionserver.MemStoreLAB;
2628
import org.apache.hadoop.hbase.util.Pair;
2729
import org.apache.yetus.audience.InterfaceAudience;
@@ -93,11 +95,16 @@ public static void checkForClusterFreeHeapMemoryLimit(Configuration conf) {
9395
) {
9496
throw new RuntimeException("Current heap configuration for MemStore and BlockCache exceeds "
9597
+ "the threshold required for successful cluster operation. "
96-
+ "The combined value cannot exceed 0.8. Please check "
97-
+ "the settings for hbase.regionserver.global.memstore.size and "
98-
+ "hfile.block.cache.size in your configuration. "
99-
+ "hbase.regionserver.global.memstore.size is " + globalMemstoreSize
100-
+ " hfile.block.cache.size is " + blockCacheUpperLimit);
98+
+ "The combined value cannot exceed 0.8. Please check " + "the settings for "
99+
+ MEMSTORE_SIZE_KEY + " and either " + HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + " or "
100+
+ HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + " in your configuration. " + MEMSTORE_SIZE_KEY
101+
+ "=" + globalMemstoreSize + ", " + HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + "="
102+
+ conf.get(HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY) + ", "
103+
+ HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + "="
104+
+ conf.get(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY) + ". (Note: If both "
105+
+ HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + " and "
106+
+ HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + " are set, " + "the system will use "
107+
+ HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + ")");
101108
}
102109
}
103110

@@ -195,10 +202,30 @@ public static long getOnheapGlobalMemStoreSize(Configuration conf) {
195202
* Retrieve configured size for on heap block cache as percentage of total heap.
196203
*/
197204
public static float getBlockCacheHeapPercent(final Configuration conf) {
198-
// L1 block cache is always on heap
199-
float l1CachePercent = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
205+
// Check if an explicit block cache size is configured.
206+
long l1CacheSizeInBytes = getBlockCacheSizeInBytes(conf);
207+
if (l1CacheSizeInBytes > 0) {
208+
final MemoryUsage usage = safeGetHeapMemoryUsage();
209+
return usage == null ? 0 : (float) l1CacheSizeInBytes / usage.getMax();
210+
}
211+
212+
return conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
200213
HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
201-
return l1CachePercent;
214+
}
215+
216+
/**
217+
* Retrieve an explicit block cache size in bytes in the configuration.
218+
* @param conf used to read cache configs
219+
* @return the number of bytes to use for LRU, negative if disabled.
220+
* @throws IllegalArgumentException if HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY format is invalid
221+
*/
222+
public static long getBlockCacheSizeInBytes(Configuration conf) {
223+
final String key = HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY;
224+
try {
225+
return Long.parseLong(conf.get(key));
226+
} catch (NumberFormatException e) {
227+
return (long) StorageSize.getStorageSize(conf.get(key), -1, StorageUnit.BYTES);
228+
}
202229
}
203230

204231
/**
@@ -207,27 +234,30 @@ public static float getBlockCacheHeapPercent(final Configuration conf) {
207234
* @throws IllegalArgumentException if HFILE_BLOCK_CACHE_SIZE_KEY is > 1.0
208235
*/
209236
public static long getOnHeapCacheSize(final Configuration conf) {
210-
float cachePercentage = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
211-
HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
237+
final float cachePercentage = getBlockCacheHeapPercent(conf);
212238
if (cachePercentage <= 0.0001f) {
213239
return -1;
214240
}
215241
if (cachePercentage > 1.0) {
216242
throw new IllegalArgumentException(
217243
HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + " must be between 0.0 and 1.0, and not > 1.0");
218244
}
219-
long max = -1L;
245+
220246
final MemoryUsage usage = safeGetHeapMemoryUsage();
221-
if (usage != null) {
222-
max = usage.getMax();
247+
if (usage == null) {
248+
return -1;
223249
}
250+
final long heapMax = usage.getMax();
224251
float onHeapCacheFixedSize =
225252
(float) conf.getLong(HConstants.HFILE_ONHEAP_BLOCK_CACHE_FIXED_SIZE_KEY,
226-
HConstants.HFILE_ONHEAP_BLOCK_CACHE_FIXED_SIZE_DEFAULT) / max;
253+
HConstants.HFILE_ONHEAP_BLOCK_CACHE_FIXED_SIZE_DEFAULT) / heapMax;
227254
// Calculate the amount of heap to give the heap.
228-
return (onHeapCacheFixedSize > 0 && onHeapCacheFixedSize < cachePercentage)
229-
? (long) (max * onHeapCacheFixedSize)
230-
: (long) (max * cachePercentage);
255+
if (onHeapCacheFixedSize > 0 && onHeapCacheFixedSize < cachePercentage) {
256+
return (long) (heapMax * onHeapCacheFixedSize);
257+
} else {
258+
final long cacheSizeInBytes = getBlockCacheSizeInBytes(conf);
259+
return cacheSizeInBytes > 0 ? cacheSizeInBytes : (long) (heapMax * cachePercentage);
260+
}
231261
}
232262

233263
/**
@@ -243,5 +273,4 @@ public static long getBucketCacheSize(final Configuration conf) {
243273
}
244274
return (long) (bucketCacheSize * 1024 * 1024);
245275
}
246-
247276
}

hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package org.apache.hadoop.hbase.regionserver;
1919

20+
import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY;
2021
import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_SIZE_KEY;
2122

2223
import java.lang.management.MemoryUsage;
@@ -128,8 +129,7 @@ private ResizableBlockCache toResizableBlockCache(BlockCache blockCache) {
128129
private boolean doInit(Configuration conf) {
129130
boolean tuningEnabled = true;
130131
globalMemStorePercent = MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, false);
131-
blockCachePercent =
132-
conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
132+
blockCachePercent = MemorySizeUtil.getBlockCacheHeapPercent(conf);
133133
MemorySizeUtil.checkForClusterFreeHeapMemoryLimit(conf);
134134
// Initialize max and min range for memstore heap space
135135
globalMemStorePercentMinRange =
@@ -160,16 +160,20 @@ private boolean doInit(Configuration conf) {
160160
blockCachePercentMinRange = conf.getFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercent);
161161
blockCachePercentMaxRange = conf.getFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercent);
162162
if (blockCachePercent < blockCachePercentMinRange) {
163-
LOG.warn("Setting " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " to " + blockCachePercent
164-
+ ", same value as " + HFILE_BLOCK_CACHE_SIZE_KEY
165-
+ " because supplied value greater than initial block cache size.");
163+
LOG.warn(
164+
"Setting {} to {} (lookup order: {} -> {}), "
165+
+ "because supplied value greater than initial block cache size.",
166+
BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercent, HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY,
167+
HFILE_BLOCK_CACHE_SIZE_KEY);
166168
blockCachePercentMinRange = blockCachePercent;
167169
conf.setFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercentMinRange);
168170
}
169171
if (blockCachePercent > blockCachePercentMaxRange) {
170-
LOG.warn("Setting " + BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " to " + blockCachePercent
171-
+ ", same value as " + HFILE_BLOCK_CACHE_SIZE_KEY
172-
+ " because supplied value less than initial block cache size.");
172+
LOG.warn(
173+
"Setting {} to {} (lookup order: {} -> {}), "
174+
+ "because supplied value less than initial block cache size.",
175+
BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercent, HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY,
176+
HFILE_BLOCK_CACHE_SIZE_KEY);
173177
blockCachePercentMaxRange = blockCachePercent;
174178
conf.setFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercentMaxRange);
175179
}

hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,14 @@ public void testGetOnHeapCacheSize() {
394394
long onHeapCacheSize = MemorySizeUtil.getOnHeapCacheSize(copyConf);
395395
assertEquals(null, copyConf.get(HConstants.HFILE_ONHEAP_BLOCK_CACHE_FIXED_SIZE_KEY));
396396
assertTrue(onHeapCacheSize > 0 && onHeapCacheSize != fixedSize);
397+
// when HBASE_BLOCK_CACHE_MEMORY_SIZE is set in number
398+
copyConf.setLong(HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY, 3 * 1024 * 1024);
399+
onHeapCacheSize = MemorySizeUtil.getOnHeapCacheSize(copyConf);
400+
assertEquals(3 * 1024 * 1024, onHeapCacheSize);
401+
// when HBASE_BLOCK_CACHE_MEMORY_SIZE is set in human-readable format
402+
copyConf.set(HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY, "2m");
403+
onHeapCacheSize = MemorySizeUtil.getOnHeapCacheSize(copyConf);
404+
assertEquals(2 * 1024 * 1024, onHeapCacheSize);
397405
// when HBASE_BLOCK_CACHE_FIXED_SIZE_KEY is set, it will be a fixed size
398406
copyConf.setLong(HConstants.HFILE_ONHEAP_BLOCK_CACHE_FIXED_SIZE_KEY, fixedSize);
399407
onHeapCacheSize = MemorySizeUtil.getOnHeapCacheSize(copyConf);

0 commit comments

Comments
 (0)