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.io.util;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertThrows;
022import static org.junit.jupiter.api.Assertions.assertTrue;
023
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.hbase.HConstants;
026import org.apache.hadoop.hbase.testclassification.MiscTests;
027import org.apache.hadoop.hbase.testclassification.SmallTests;
028import org.junit.jupiter.api.BeforeEach;
029import org.junit.jupiter.api.Tag;
030import org.junit.jupiter.api.Test;
031
032@Tag(MiscTests.TAG)
033@Tag(SmallTests.TAG)
034public class TestMemorySizeUtil {
035
036  private Configuration conf;
037
038  @BeforeEach
039  public void setup() {
040    conf = new Configuration();
041  }
042
043  @Test
044  public void testValidateRegionServerHeapMemoryAllocation() {
045    // when memstore size + block cache size + default free heap min size == 1.0
046    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.4f);
047    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.4f);
048    assertEquals(HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD, 0.2f, 0.0f);
049    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
050
051    // when memstore size + block cache size + default free heap min size > 1.0
052    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.5f);
053    assertThrows(RuntimeException.class,
054      () -> MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf));
055
056    // when free heap min size is set to 0, it should not throw an exception
057    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.5f);
058    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.5f);
059    conf.setLong(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, 0L);
060    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
061
062    // when free heap min size is set to a negative value, it should be regarded as default value
063    conf.setLong(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, -1024L);
064    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.4f);
065    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.4f);
066    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
067
068    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.41f);
069    assertThrows(RuntimeException.class,
070      () -> MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf));
071  }
072
073  @Test
074  public void testGetRegionServerMinFreeHeapFraction() {
075    // when setting is not set, it should return the default value
076    conf.set(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, "");
077    float minFreeHeapFraction = MemorySizeUtil.getRegionServerMinFreeHeapFraction(conf);
078    assertEquals(HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD, minFreeHeapFraction, 0.0f);
079
080    // when setting to 0, it should return 0.0f
081    conf.set(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, "0");
082    minFreeHeapFraction = MemorySizeUtil.getRegionServerMinFreeHeapFraction(conf);
083    assertEquals(0.0f, minFreeHeapFraction, 0.0f);
084  }
085
086  @Test
087  public void testGetMemstoreSizeInBytes() {
088    // when memstore size is not set, it should return -1
089    long memstoreSizeInBytes = MemorySizeUtil.getMemstoreSizeInBytes(conf);
090    assertEquals(-1, memstoreSizeInBytes);
091
092    long expectedMemstoreSizeInBytes = 123456L;
093    conf.setLong(MemorySizeUtil.MEMSTORE_MEMORY_SIZE_KEY, expectedMemstoreSizeInBytes);
094    memstoreSizeInBytes = MemorySizeUtil.getMemstoreSizeInBytes(conf);
095    assertEquals(expectedMemstoreSizeInBytes, memstoreSizeInBytes);
096
097    conf.set(MemorySizeUtil.MEMSTORE_MEMORY_SIZE_KEY, "10m");
098    memstoreSizeInBytes = MemorySizeUtil.getMemstoreSizeInBytes(conf);
099    assertEquals(10 * 1024 * 1024, memstoreSizeInBytes);
100
101    conf.set(MemorySizeUtil.MEMSTORE_MEMORY_SIZE_KEY, "2GB");
102    memstoreSizeInBytes = MemorySizeUtil.getMemstoreSizeInBytes(conf);
103    assertEquals(2L * 1024 * 1024 * 1024, memstoreSizeInBytes);
104  }
105
106  @Test
107  public void testGetGlobalMemStoreHeapPercent() {
108    // set memstore size to a small value
109    conf.setLong(MemorySizeUtil.MEMSTORE_MEMORY_SIZE_KEY, 1);
110    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.4f);
111    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.5f);
112    assertEquals(HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD, 0.2f, 0.0f);
113    float globalMemStoreHeapPercent = MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, true);
114    assertTrue(globalMemStoreHeapPercent > 0.0f);
115    assertTrue(globalMemStoreHeapPercent < 0.4f);
116    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
117  }
118}