001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY; 021import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_SIZE_KEY; 022import static org.apache.hadoop.hbase.io.util.MemorySizeUtil.MEMSTORE_MEMORY_SIZE_KEY; 023import static org.apache.hadoop.hbase.io.util.MemorySizeUtil.MEMSTORE_SIZE_KEY; 024 025import java.lang.management.MemoryUsage; 026import java.util.ArrayList; 027import java.util.List; 028import java.util.concurrent.atomic.AtomicLong; 029import org.apache.hadoop.conf.Configuration; 030import org.apache.hadoop.hbase.ChoreService; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.ScheduledChore; 033import org.apache.hadoop.hbase.Server; 034import org.apache.hadoop.hbase.io.hfile.BlockCache; 035import org.apache.hadoop.hbase.io.hfile.CombinedBlockCache; 036import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache; 037import org.apache.hadoop.hbase.io.util.MemorySizeUtil; 038import org.apache.hadoop.util.ReflectionUtils; 039import org.apache.yetus.audience.InterfaceAudience; 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043/** 044 * Manages tuning of Heap memory using <code>HeapMemoryTuner</code>. Most part of the heap memory is 045 * split between Memstores and BlockCache. This manager helps in tuning sizes of both these 046 * dynamically, as per the R/W load on the servers. 047 */ 048@InterfaceAudience.Private 049public class HeapMemoryManager { 050 private static final Logger LOG = LoggerFactory.getLogger(HeapMemoryManager.class); 051 private static final int CONVERT_TO_PERCENTAGE = 100; 052 053 public static final String BLOCK_CACHE_SIZE_MAX_RANGE_KEY = "hfile.block.cache.size.max.range"; 054 public static final String BLOCK_CACHE_SIZE_MIN_RANGE_KEY = "hfile.block.cache.size.min.range"; 055 public static final String MEMSTORE_SIZE_MAX_RANGE_KEY = 056 "hbase.regionserver.global.memstore.size.max.range"; 057 public static final String MEMSTORE_SIZE_MIN_RANGE_KEY = 058 "hbase.regionserver.global.memstore.size.min.range"; 059 public static final String HBASE_RS_HEAP_MEMORY_TUNER_PERIOD = 060 "hbase.regionserver.heapmemory.tuner.period"; 061 public static final int HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD = 60 * 1000; 062 public static final String HBASE_RS_HEAP_MEMORY_TUNER_CLASS = 063 "hbase.regionserver.heapmemory.tuner.class"; 064 065 public static final float HEAP_OCCUPANCY_ERROR_VALUE = -0.0f; 066 067 private float globalMemStorePercent; 068 private float globalMemStorePercentMinRange; 069 private float globalMemStorePercentMaxRange; 070 071 private float blockCachePercent; 072 private float blockCachePercentMinRange; 073 private float blockCachePercentMaxRange; 074 075 private float heapOccupancyPercent; 076 077 private final ResizableBlockCache blockCache; 078 // TODO : remove this and mark regionServerAccounting as the observer directly 079 private final FlushRequester memStoreFlusher; 080 private final Server server; 081 private final RegionServerAccounting regionServerAccounting; 082 083 private HeapMemoryTunerChore heapMemTunerChore = null; 084 private final boolean tunerOn; 085 private final int defaultChorePeriod; 086 private final float heapOccupancyLowWatermark; 087 private final float minFreeHeapFraction; 088 089 private final long maxHeapSize; 090 { 091 // note that this initialization still isn't threadsafe, because updating a long isn't atomic. 092 long tempMaxHeap = -1L; 093 try { 094 final MemoryUsage usage = MemorySizeUtil.safeGetHeapMemoryUsage(); 095 if (usage != null) { 096 tempMaxHeap = usage.getMax(); 097 } 098 } finally { 099 maxHeapSize = tempMaxHeap; 100 } 101 } 102 103 private MetricsHeapMemoryManager metricsHeapMemoryManager; 104 105 private List<HeapMemoryTuneObserver> tuneObservers = new ArrayList<>(); 106 107 HeapMemoryManager(BlockCache blockCache, FlushRequester memStoreFlusher, Server server, 108 RegionServerAccounting regionServerAccounting) { 109 Configuration conf = server.getConfiguration(); 110 this.blockCache = toResizableBlockCache(blockCache); 111 this.memStoreFlusher = memStoreFlusher; 112 this.server = server; 113 this.regionServerAccounting = regionServerAccounting; 114 this.minFreeHeapFraction = MemorySizeUtil.getRegionServerMinFreeHeapFraction(conf); 115 this.tunerOn = doInit(conf); 116 this.defaultChorePeriod = 117 conf.getInt(HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD); 118 this.heapOccupancyLowWatermark = conf.getFloat(HConstants.HEAP_OCCUPANCY_LOW_WATERMARK_KEY, 119 HConstants.DEFAULT_HEAP_OCCUPANCY_LOW_WATERMARK); 120 metricsHeapMemoryManager = new MetricsHeapMemoryManager(); 121 } 122 123 private ResizableBlockCache toResizableBlockCache(BlockCache blockCache) { 124 if (blockCache instanceof CombinedBlockCache) { 125 return ((CombinedBlockCache) blockCache).getFirstLevelCache(); 126 } else { 127 return (ResizableBlockCache) blockCache; 128 } 129 } 130 131 private boolean doInit(Configuration conf) { 132 boolean tuningEnabled = true; 133 globalMemStorePercent = MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, false); 134 blockCachePercent = MemorySizeUtil.getBlockCacheHeapPercent(conf); 135 MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf); 136 // Initialize max and min range for memstore heap space 137 globalMemStorePercentMinRange = 138 conf.getFloat(MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercent); 139 globalMemStorePercentMaxRange = 140 conf.getFloat(MEMSTORE_SIZE_MAX_RANGE_KEY, globalMemStorePercent); 141 if (globalMemStorePercent < globalMemStorePercentMinRange) { 142 LOG.warn( 143 "Setting {} to {} (lookup order: {} -> {}), " 144 + "because supplied value greater than initial memstore size.", 145 MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercent, MEMSTORE_MEMORY_SIZE_KEY, 146 MEMSTORE_SIZE_KEY); 147 globalMemStorePercentMinRange = globalMemStorePercent; 148 conf.setFloat(MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercentMinRange); 149 } 150 if (globalMemStorePercent > globalMemStorePercentMaxRange) { 151 LOG.warn( 152 "Setting {} to {} (lookup order: {} -> {}), " 153 + "because supplied value less than initial memstore size.", 154 MEMSTORE_SIZE_MAX_RANGE_KEY, globalMemStorePercent, MEMSTORE_MEMORY_SIZE_KEY, 155 MEMSTORE_SIZE_KEY); 156 globalMemStorePercentMaxRange = globalMemStorePercent; 157 conf.setFloat(MEMSTORE_SIZE_MAX_RANGE_KEY, globalMemStorePercentMaxRange); 158 } 159 if ( 160 globalMemStorePercent == globalMemStorePercentMinRange 161 && globalMemStorePercent == globalMemStorePercentMaxRange 162 ) { 163 tuningEnabled = false; 164 } 165 // Initialize max and min range for block cache 166 blockCachePercentMinRange = conf.getFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercent); 167 blockCachePercentMaxRange = conf.getFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercent); 168 if (blockCachePercent < blockCachePercentMinRange) { 169 LOG.warn( 170 "Setting {} to {} (lookup order: {} -> {}), " 171 + "because supplied value greater than initial block cache size.", 172 BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercent, HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY, 173 HFILE_BLOCK_CACHE_SIZE_KEY); 174 blockCachePercentMinRange = blockCachePercent; 175 conf.setFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercentMinRange); 176 } 177 if (blockCachePercent > blockCachePercentMaxRange) { 178 LOG.warn( 179 "Setting {} to {} (lookup order: {} -> {}), " 180 + "because supplied value less than initial block cache size.", 181 BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercent, HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY, 182 HFILE_BLOCK_CACHE_SIZE_KEY); 183 blockCachePercentMaxRange = blockCachePercent; 184 conf.setFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercentMaxRange); 185 } 186 if ( 187 tuningEnabled && blockCachePercent == blockCachePercentMinRange 188 && blockCachePercent == blockCachePercentMaxRange 189 ) { 190 tuningEnabled = false; 191 } 192 193 checkHeapMemoryLimits(MEMSTORE_SIZE_MAX_RANGE_KEY, globalMemStorePercentMaxRange, 194 BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercentMinRange); 195 checkHeapMemoryLimits(MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercentMinRange, 196 BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercentMaxRange); 197 198 return tuningEnabled; 199 } 200 201 public void start(ChoreService service) { 202 LOG.info("Starting, tuneOn={}", this.tunerOn); 203 this.heapMemTunerChore = new HeapMemoryTunerChore(); 204 service.scheduleChore(heapMemTunerChore); 205 if (tunerOn) { 206 // Register HeapMemoryTuner as a memstore flush listener 207 memStoreFlusher.registerFlushRequestListener(heapMemTunerChore); 208 } 209 } 210 211 public void stop() { 212 // The thread is Daemon. Just interrupting the ongoing process. 213 LOG.info("Stopping"); 214 this.heapMemTunerChore.shutdown(true); 215 } 216 217 public void registerTuneObserver(HeapMemoryTuneObserver observer) { 218 this.tuneObservers.add(observer); 219 } 220 221 // Used by the test cases. 222 boolean isTunerOn() { 223 return this.tunerOn; 224 } 225 226 /** Returns heap occupancy percentage, 0 <= n <= 1. or -0.0 for error asking JVM */ 227 public float getHeapOccupancyPercent() { 228 return this.heapOccupancyPercent == Float.MAX_VALUE 229 ? HEAP_OCCUPANCY_ERROR_VALUE 230 : this.heapOccupancyPercent; 231 } 232 233 private boolean isHeapMemoryUsageExceedingLimit(float memStoreFraction, 234 float blockCacheFraction) { 235 // Use integer percentage to avoid subtle float precision issues and ensure consistent 236 // comparison. This also maintains backward compatibility with previous logic relying on int 237 // truncation. 238 int memStorePercent = (int) (memStoreFraction * CONVERT_TO_PERCENTAGE); 239 int blockCachePercent = (int) (blockCacheFraction * CONVERT_TO_PERCENTAGE); 240 int minFreeHeapPercent = (int) (this.minFreeHeapFraction * CONVERT_TO_PERCENTAGE); 241 242 return memStorePercent + blockCachePercent + minFreeHeapPercent > CONVERT_TO_PERCENTAGE; 243 } 244 245 private void checkHeapMemoryLimits(String memStoreConfKey, float memStoreFraction, 246 String blockCacheConfKey, float blockCacheFraction) { 247 if (isHeapMemoryUsageExceedingLimit(memStoreFraction, blockCacheFraction)) { 248 throw new RuntimeException(String.format( 249 "Current heap configuration for MemStore and BlockCache exceeds the allowed heap usage. " 250 + "At least %.2f of the heap must remain free to ensure stable RegionServer operation. " 251 + "Please check the settings for %s and %s in your configuration. " 252 + "%s is %.2f and %s is %.2f", 253 minFreeHeapFraction, memStoreConfKey, blockCacheConfKey, memStoreConfKey, memStoreFraction, 254 blockCacheConfKey, blockCacheFraction)); 255 } 256 } 257 258 private class HeapMemoryTunerChore extends ScheduledChore implements FlushRequestListener { 259 private HeapMemoryTuner heapMemTuner; 260 private AtomicLong blockedFlushCount = new AtomicLong(); 261 private AtomicLong unblockedFlushCount = new AtomicLong(); 262 private long evictCount = 0L; 263 private long cacheMissCount = 0L; 264 private TunerContext tunerContext = new TunerContext(); 265 private boolean alarming = false; 266 267 public HeapMemoryTunerChore() { 268 super(server.getServerName() + "-HeapMemoryTunerChore", server, defaultChorePeriod); 269 Class<? extends HeapMemoryTuner> tunerKlass = server.getConfiguration().getClass( 270 HBASE_RS_HEAP_MEMORY_TUNER_CLASS, DefaultHeapMemoryTuner.class, HeapMemoryTuner.class); 271 heapMemTuner = ReflectionUtils.newInstance(tunerKlass, server.getConfiguration()); 272 tunerContext.setOffheapMemStore(regionServerAccounting.isOffheap()); 273 } 274 275 @Override 276 protected void chore() { 277 // Sample heap occupancy 278 final MemoryUsage usage = MemorySizeUtil.safeGetHeapMemoryUsage(); 279 if (usage != null) { 280 heapOccupancyPercent = (float) usage.getUsed() / (float) usage.getCommitted(); 281 } else { 282 // previously, an exception would have meant death for the tuning chore 283 // so switch to alarming so that we similarly stop tuning until we get 284 // heap usage information again. 285 heapOccupancyPercent = Float.MAX_VALUE; 286 } 287 // If we are above the heap occupancy alarm low watermark, switch to short 288 // sleeps for close monitoring. Stop autotuning, we are in a danger zone. 289 if (heapOccupancyPercent >= heapOccupancyLowWatermark) { 290 if (!alarming) { 291 LOG.warn("heapOccupancyPercent " + heapOccupancyPercent 292 + " is above heap occupancy alarm watermark (" + heapOccupancyLowWatermark + ")"); 293 alarming = true; 294 } 295 metricsHeapMemoryManager.increaseAboveHeapOccupancyLowWatermarkCounter(); 296 triggerNow(); 297 try { 298 // Need to sleep ourselves since we've told the chore's sleeper 299 // to skip the next sleep cycle. 300 Thread.sleep(1000); 301 } catch (InterruptedException e) { 302 // Interrupted, propagate 303 Thread.currentThread().interrupt(); 304 } 305 } else { 306 if (alarming) { 307 LOG.info("heapOccupancyPercent " + heapOccupancyPercent 308 + " is now below the heap occupancy alarm watermark (" + heapOccupancyLowWatermark 309 + ")"); 310 alarming = false; 311 } 312 } 313 // Autotune if tuning is enabled and allowed 314 if (tunerOn && !alarming) { 315 tune(); 316 } 317 } 318 319 private void tune() { 320 // TODO check if we can increase the memory boundaries 321 // while remaining in the limits 322 long curEvictCount; 323 long curCacheMisCount; 324 long blockedFlushCnt; 325 long unblockedFlushCnt; 326 curEvictCount = blockCache.getStats().getEvictedCount(); 327 tunerContext.setEvictCount(curEvictCount - evictCount); 328 evictCount = curEvictCount; 329 curCacheMisCount = blockCache.getStats().getMissCachingCount(); 330 tunerContext.setCacheMissCount(curCacheMisCount - cacheMissCount); 331 cacheMissCount = curCacheMisCount; 332 blockedFlushCnt = blockedFlushCount.getAndSet(0); 333 tunerContext.setBlockedFlushCount(blockedFlushCnt); 334 metricsHeapMemoryManager.updateBlockedFlushCount(blockedFlushCnt); 335 unblockedFlushCnt = unblockedFlushCount.getAndSet(0); 336 tunerContext.setUnblockedFlushCount(unblockedFlushCnt); 337 metricsHeapMemoryManager.updateUnblockedFlushCount(unblockedFlushCnt); 338 tunerContext.setCurBlockCacheUsed((float) blockCache.getCurrentSize() / maxHeapSize); 339 metricsHeapMemoryManager.setCurBlockCacheSizeGauge(blockCache.getCurrentSize()); 340 long globalMemstoreDataSize = regionServerAccounting.getGlobalMemStoreDataSize(); 341 long globalMemstoreHeapSize = regionServerAccounting.getGlobalMemStoreHeapSize(); 342 long globalMemStoreOffHeapSize = regionServerAccounting.getGlobalMemStoreOffHeapSize(); 343 tunerContext.setCurMemStoreUsed((float) globalMemstoreHeapSize / maxHeapSize); 344 metricsHeapMemoryManager.setCurMemStoreSizeGauge(globalMemstoreDataSize); 345 metricsHeapMemoryManager.setCurMemStoreOnHeapSizeGauge(globalMemstoreHeapSize); 346 metricsHeapMemoryManager.setCurMemStoreOffHeapSizeGauge(globalMemStoreOffHeapSize); 347 tunerContext.setCurBlockCacheSize(blockCachePercent); 348 tunerContext.setCurMemStoreSize(globalMemStorePercent); 349 TunerResult result = null; 350 try { 351 result = this.heapMemTuner.tune(tunerContext); 352 } catch (Throwable t) { 353 LOG.error("Exception thrown from the HeapMemoryTuner implementation", t); 354 } 355 if (result != null && result.needsTuning()) { 356 float memstoreSize = result.getMemStoreSize(); 357 float blockCacheSize = result.getBlockCacheSize(); 358 LOG.debug("From HeapMemoryTuner new memstoreSize: " + memstoreSize 359 + ". new blockCacheSize: " + blockCacheSize); 360 if (memstoreSize < globalMemStorePercentMinRange) { 361 LOG.info("New memstoreSize from HeapMemoryTuner " + memstoreSize + " is below min level " 362 + globalMemStorePercentMinRange + ". Resetting memstoreSize to min size"); 363 memstoreSize = globalMemStorePercentMinRange; 364 } else if (memstoreSize > globalMemStorePercentMaxRange) { 365 LOG.info("New memstoreSize from HeapMemoryTuner " + memstoreSize + " is above max level " 366 + globalMemStorePercentMaxRange + ". Resetting memstoreSize to max size"); 367 memstoreSize = globalMemStorePercentMaxRange; 368 } 369 if (blockCacheSize < blockCachePercentMinRange) { 370 LOG.info( 371 "New blockCacheSize from HeapMemoryTuner " + blockCacheSize + " is below min level " 372 + blockCachePercentMinRange + ". Resetting blockCacheSize to min size"); 373 blockCacheSize = blockCachePercentMinRange; 374 } else if (blockCacheSize > blockCachePercentMaxRange) { 375 LOG.info( 376 "New blockCacheSize from HeapMemoryTuner " + blockCacheSize + " is above max level " 377 + blockCachePercentMaxRange + ". Resetting blockCacheSize to min size"); 378 blockCacheSize = blockCachePercentMaxRange; 379 } 380 381 if (isHeapMemoryUsageExceedingLimit(memstoreSize, blockCacheSize)) { 382 LOG.info("Current heap configuration from HeapMemoryTuner exceeds " 383 + "the allowed heap usage. At least " + minFreeHeapFraction 384 + " of the heap must remain free to ensure stable RegionServer operation. " 385 + MEMSTORE_SIZE_KEY + " is " + memstoreSize + " and " + HFILE_BLOCK_CACHE_SIZE_KEY 386 + " is " + blockCacheSize); 387 // NOTE: In the future, we might adjust values to not exceed limits, 388 // but for now tuning is skipped if over threshold. 389 } else { 390 int memStoreDeltaSize = 391 (int) ((memstoreSize - globalMemStorePercent) * CONVERT_TO_PERCENTAGE); 392 int blockCacheDeltaSize = 393 (int) ((blockCacheSize - blockCachePercent) * CONVERT_TO_PERCENTAGE); 394 metricsHeapMemoryManager.updateMemStoreDeltaSizeHistogram(memStoreDeltaSize); 395 metricsHeapMemoryManager.updateBlockCacheDeltaSizeHistogram(blockCacheDeltaSize); 396 long newBlockCacheSize = (long) (maxHeapSize * blockCacheSize); 397 // we could have got an increase or decrease in size for the offheap memstore 398 // also if the flush had happened due to heap overhead. In that case it is ok 399 // to adjust the onheap memstore limit configs 400 long newMemstoreSize = (long) (maxHeapSize * memstoreSize); 401 LOG.info("Setting block cache heap size to " + newBlockCacheSize 402 + " and memstore heap size to " + newMemstoreSize); 403 blockCachePercent = blockCacheSize; 404 blockCache.setMaxSize(newBlockCacheSize); 405 globalMemStorePercent = memstoreSize; 406 // Internally sets it to RegionServerAccounting 407 // TODO : Set directly on RSAccounting?? 408 memStoreFlusher.setGlobalMemStoreLimit(newMemstoreSize); 409 for (HeapMemoryTuneObserver observer : tuneObservers) { 410 // Risky.. If this newMemstoreSize decreases we reduce the count in offheap chunk pool 411 observer.onHeapMemoryTune(newMemstoreSize, newBlockCacheSize); 412 } 413 } 414 } else { 415 metricsHeapMemoryManager.increaseTunerDoNothingCounter(); 416 if (LOG.isDebugEnabled()) { 417 LOG.debug("No changes made by HeapMemoryTuner."); 418 } 419 } 420 } 421 422 @Override 423 public void flushRequested(FlushType type, Region region) { 424 switch (type) { 425 case ABOVE_ONHEAP_HIGHER_MARK: 426 blockedFlushCount.incrementAndGet(); 427 break; 428 case ABOVE_ONHEAP_LOWER_MARK: 429 unblockedFlushCount.incrementAndGet(); 430 break; 431 // Removed the counting of the offheap related flushes (after reviews). Will add later if 432 // needed 433 default: 434 // In case of any other flush don't do any action. 435 break; 436 } 437 } 438 } 439 440 /** 441 * POJO to pass all the relevant information required to do the heap memory tuning. It holds the 442 * flush counts and block cache evictions happened within the interval. Also holds the current 443 * heap percentage allocated for memstore and block cache. 444 */ 445 public static final class TunerContext { 446 private long blockedFlushCount; 447 private long unblockedFlushCount; 448 private long evictCount; 449 private long cacheMissCount; 450 private float curBlockCacheUsed; 451 private float curMemStoreUsed; 452 private float curMemStoreSize; 453 private float curBlockCacheSize; 454 private boolean offheapMemstore; 455 456 public long getBlockedFlushCount() { 457 return blockedFlushCount; 458 } 459 460 public void setBlockedFlushCount(long blockedFlushCount) { 461 this.blockedFlushCount = blockedFlushCount; 462 } 463 464 public long getUnblockedFlushCount() { 465 return unblockedFlushCount; 466 } 467 468 public void setUnblockedFlushCount(long unblockedFlushCount) { 469 this.unblockedFlushCount = unblockedFlushCount; 470 } 471 472 public long getEvictCount() { 473 return evictCount; 474 } 475 476 public void setEvictCount(long evictCount) { 477 this.evictCount = evictCount; 478 } 479 480 public float getCurMemStoreSize() { 481 return curMemStoreSize; 482 } 483 484 public void setCurMemStoreSize(float curMemStoreSize) { 485 this.curMemStoreSize = curMemStoreSize; 486 } 487 488 public float getCurBlockCacheSize() { 489 return curBlockCacheSize; 490 } 491 492 public void setCurBlockCacheSize(float curBlockCacheSize) { 493 this.curBlockCacheSize = curBlockCacheSize; 494 } 495 496 public long getCacheMissCount() { 497 return cacheMissCount; 498 } 499 500 public void setCacheMissCount(long cacheMissCount) { 501 this.cacheMissCount = cacheMissCount; 502 } 503 504 public float getCurBlockCacheUsed() { 505 return curBlockCacheUsed; 506 } 507 508 public void setCurBlockCacheUsed(float curBlockCacheUsed) { 509 this.curBlockCacheUsed = curBlockCacheUsed; 510 } 511 512 public float getCurMemStoreUsed() { 513 return curMemStoreUsed; 514 } 515 516 public void setCurMemStoreUsed(float d) { 517 this.curMemStoreUsed = d; 518 } 519 520 public void setOffheapMemStore(boolean offheapMemstore) { 521 this.offheapMemstore = offheapMemstore; 522 } 523 524 public boolean isOffheapMemStore() { 525 return this.offheapMemstore; 526 } 527 } 528 529 /** 530 * POJO which holds the result of memory tuning done by HeapMemoryTuner implementation. It 531 * includes the new heap percentage for memstore and block cache. 532 */ 533 public static final class TunerResult { 534 private float memstoreSize; 535 private float blockCacheSize; 536 private final boolean needsTuning; 537 538 public TunerResult(boolean needsTuning) { 539 this.needsTuning = needsTuning; 540 } 541 542 public float getMemStoreSize() { 543 return memstoreSize; 544 } 545 546 public void setMemStoreSize(float memstoreSize) { 547 this.memstoreSize = memstoreSize; 548 } 549 550 public float getBlockCacheSize() { 551 return blockCacheSize; 552 } 553 554 public void setBlockCacheSize(float blockCacheSize) { 555 this.blockCacheSize = blockCacheSize; 556 } 557 558 public boolean needsTuning() { 559 return needsTuning; 560 } 561 } 562 563 /** 564 * Every class that wants to observe heap memory tune actions must implement this interface. 565 */ 566 public static interface HeapMemoryTuneObserver { 567 568 /** 569 * This method would be called by HeapMemoryManger when a heap memory tune action took place. 570 * @param newMemstoreSize The newly calculated global memstore size 571 * @param newBlockCacheSize The newly calculated global blockcache size 572 */ 573 void onHeapMemoryTune(long newMemstoreSize, long newBlockCacheSize); 574 } 575}