.../hadoop/hbase/regionserver/TestMemStoreLAB.java | 98 +++++++++++++--------- .../regionserver/TestMemstoreLABWithoutPool.java | 2 +- 2 files changed, 58 insertions(+), 42 deletions(-) diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java index 6696e43..06ee87b 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java @@ -190,56 +190,72 @@ public class TestMemStoreLAB { */ @Test public void testLABChunkQueue() throws Exception { - MemStoreLABImpl mslab = new MemStoreLABImpl(); - // by default setting, there should be no chunks initialized in the pool - assertTrue(mslab.getPooledChunks().isEmpty()); - // reset mslab with chunk pool - Configuration conf = HBaseConfiguration.create(); - conf.setDouble(MemStoreLAB.CHUNK_POOL_MAXSIZE_KEY, 0.1); - // set chunk size to default max alloc size, so we could easily trigger chunk retirement - conf.setLong(MemStoreLABImpl.CHUNK_SIZE_KEY, MemStoreLABImpl.MAX_ALLOC_DEFAULT); - // reconstruct mslab - ChunkCreator.clearDisableFlag(); - mslab = new MemStoreLABImpl(conf); - // launch multiple threads to trigger frequent chunk retirement - List threads = new ArrayList<>(); - final KeyValue kv = new KeyValue(Bytes.toBytes("r"), Bytes.toBytes("f"), Bytes.toBytes("q"), - new byte[MemStoreLABImpl.MAX_ALLOC_DEFAULT - 24]); - for (int i = 0; i < 10; i++) { - threads.add(getChunkQueueTestThread(mslab, "testLABChunkQueue-" + i, kv)); - } - for (Thread thread : threads) { - thread.start(); - } - // let it run for some time - Thread.sleep(1000); - for (Thread thread : threads) { - thread.interrupt(); - } - boolean threadsRunning = true; - while (threadsRunning) { + ChunkCreator currentInstance = null; + try { + MemStoreLABImpl mslab = new MemStoreLABImpl(); + // by default setting, there should be no chunks initialized in the pool + assertTrue(mslab.getPooledChunks().isEmpty()); + currentInstance = ChunkCreator.INSTANCE; + ChunkCreator.INSTANCE = null; + // reset mslab with chunk pool + Configuration conf = HBaseConfiguration.create(); + conf.setDouble(MemStoreLAB.CHUNK_POOL_MAXSIZE_KEY, 0.1); + // set chunk size to default max alloc size, so we could easily trigger chunk retirement + conf.setLong(MemStoreLABImpl.CHUNK_SIZE_KEY, MemStoreLABImpl.MAX_ALLOC_DEFAULT); + // reconstruct mslab + long globalMemStoreLimit = (long) (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage() + .getMax() * MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, false)); + ChunkCreator.initialize(MemStoreLABImpl.MAX_ALLOC_DEFAULT, false, + globalMemStoreLimit, 0.1f, MemStoreLAB.POOL_INITIAL_SIZE_DEFAULT, null); + ChunkCreator.clearDisableFlag(); + mslab = new MemStoreLABImpl(conf); + // launch multiple threads to trigger frequent chunk retirement + List threads = new ArrayList<>(); + final KeyValue kv = new KeyValue(Bytes.toBytes("r"), Bytes.toBytes("f"), Bytes.toBytes("q"), + new byte[MemStoreLABImpl.MAX_ALLOC_DEFAULT - 32]); + for (int i = 0; i < 10; i++) { + threads.add(getChunkQueueTestThread(mslab, "testLABChunkQueue-" + i, kv)); + } for (Thread thread : threads) { - if (thread.isAlive()) { - threadsRunning = true; - break; + thread.start(); + } + // let it run for some time + Thread.sleep(1000); + for (Thread thread : threads) { + thread.interrupt(); + } + boolean threadsRunning = true; + boolean alive = false; + while (threadsRunning) { + alive = false; + for (Thread thread : threads) { + if (thread.isAlive()) { + alive = true; + break; + } + } + if (!alive) { + threadsRunning = false; } } - threadsRunning = false; + // none of the chunkIds would have been returned back + assertTrue("All the chunks must have been cleared", ChunkCreator.INSTANCE.size() != 0); + // close the mslab + mslab.close(); + // make sure all chunks reclaimed or removed from chunk queue + int queueLength = mslab.getPooledChunks().size(); + assertTrue("All chunks in chunk queue should be reclaimed or removed" + + " after mslab closed but actually: " + queueLength, + queueLength == 0); + } finally { + ChunkCreator.INSTANCE = currentInstance; } - // close the mslab - mslab.close(); - // none of the chunkIds would have been returned back - assertTrue("All the chunks must have been cleared", ChunkCreator.INSTANCE.size() != 0); - // make sure all chunks reclaimed or removed from chunk queue - int queueLength = mslab.getPooledChunks().size(); - assertTrue("All chunks in chunk queue should be reclaimed or removed" - + " after mslab closed but actually: " + queueLength, queueLength == 0); } private Thread getChunkQueueTestThread(final MemStoreLABImpl mslab, String threadName, Cell cellToCopyInto) { Thread thread = new Thread() { - boolean stopped = false; + volatile boolean stopped = false; @Override public void run() { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemstoreLABWithoutPool.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemstoreLABWithoutPool.java index f38a75e..1af98e9 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemstoreLABWithoutPool.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemstoreLABWithoutPool.java @@ -146,7 +146,7 @@ public class TestMemstoreLABWithoutPool { private Thread getChunkQueueTestThread(final MemStoreLABImpl mslab, String threadName, Cell cellToCopyInto) { Thread thread = new Thread() { - boolean stopped = false; + volatile boolean stopped = false; @Override public void run() {