Author: todd
Date: Mon Feb  7 21:56:05 2011
New Revision: 1068156

URL: http://svn.apache.org/viewvc?rev=1068156&view=rev
Log:
HBASE-3455. Amend patch - forgot to add TestMemStoreLAB.java

Added:
    
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java

Added: 
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java
URL: 
http://svn.apache.org/viewvc/hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java?rev=1068156&view=auto
==============================================================================
--- 
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java
 (added)
+++ 
hbase/branches/0.90/src/test/java/org/apache/hadoop/hbase/regionserver/TestMemStoreLAB.java
 Mon Feb  7 21:56:05 2011
@@ -0,0 +1,177 @@
+/**
+ * Copyright 2011 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.regionserver;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.MultithreadedTestUtil;
+import org.apache.hadoop.hbase.MultithreadedTestUtil.TestThread;
+import org.apache.hadoop.hbase.regionserver.MemStoreLAB.Allocation;
+import org.junit.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.MapMaker;
+import com.google.common.collect.Maps;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
+
+public class TestMemStoreLAB {
+
+  /**
+   * Test a bunch of random allocations
+   */
+  @Test
+  public void testLABRandomAllocation() {
+    Random rand = new Random();
+    MemStoreLAB mslab = new MemStoreLAB();
+    int expectedOff = 0;
+    byte[] lastBuffer = null;
+    // 100K iterations by 0-1K alloc -> 50MB expected
+    // should be reasonable for unit test and also cover wraparound
+    // behavior
+    for (int i = 0; i < 100000; i++) {
+      int size = rand.nextInt(1000);
+      Allocation alloc = mslab.allocateBytes(size);
+      
+      if (alloc.getData() != lastBuffer) {
+        expectedOff = 0;
+        lastBuffer = alloc.getData();
+      }
+      assertEquals(expectedOff, alloc.getOffset());
+      assertTrue("Allocation " + alloc + " overruns buffer",
+          alloc.getOffset() + size <= alloc.getData().length);
+      expectedOff += size;
+    }
+  }
+
+  @Test
+  public void testLABLargeAllocation() {
+    MemStoreLAB mslab = new MemStoreLAB();
+    Allocation alloc = mslab.allocateBytes(2*1024*1024);
+    assertNull("2MB allocation shouldn't be satisfied by LAB.",
+      alloc);
+  } 
+
+  /**
+   * Test allocation from lots of threads, making sure the results don't
+   * overlap in any way
+   */
+  @Test
+  public void testLABThreading() throws Exception {
+    Configuration conf = new Configuration();
+    MultithreadedTestUtil.TestContext ctx =
+      new MultithreadedTestUtil.TestContext(conf);
+    
+    final AtomicInteger totalAllocated = new AtomicInteger();
+    
+    final MemStoreLAB mslab = new MemStoreLAB();
+    List<List<AllocRecord>> allocations = Lists.newArrayList();
+    
+    for (int i = 0; i < 10; i++) {
+      final List<AllocRecord> allocsByThisThread = Lists.newLinkedList();
+      allocations.add(allocsByThisThread);
+      
+      TestThread t = new MultithreadedTestUtil.RepeatingTestThread(ctx) {
+        private Random r = new Random();
+        @Override
+        public void doAnAction() throws Exception {
+          int size = r.nextInt(1000);
+          Allocation alloc = mslab.allocateBytes(size);
+          totalAllocated.addAndGet(size);
+          allocsByThisThread.add(new AllocRecord(alloc, size));
+        }
+      };
+      ctx.addThread(t);
+    }
+    
+    ctx.startThreads();
+    while (totalAllocated.get() < 50*1024*1024 && ctx.shouldRun()) {
+      Thread.sleep(10);
+    }
+    ctx.stop();
+    
+    // Partition the allocations by the actual byte[] they point into,
+    // make sure offsets are unique for each chunk
+    Map<byte[], Map<Integer, AllocRecord>> mapsByChunk =
+      Maps.newHashMap();
+    
+    int sizeCounted = 0;
+    for (AllocRecord rec : Iterables.concat(allocations)) {
+      sizeCounted += rec.size;
+      if (rec.size == 0) continue;
+      
+      Map<Integer, AllocRecord> mapForThisByteArray =
+        mapsByChunk.get(rec.alloc.getData());
+      if (mapForThisByteArray == null) {
+        mapForThisByteArray = Maps.newTreeMap();
+        mapsByChunk.put(rec.alloc.getData(), mapForThisByteArray);
+      }
+      AllocRecord oldVal = mapForThisByteArray.put(rec.alloc.getOffset(), rec);
+      assertNull("Already had an entry " + oldVal + " for allocation " + rec,
+          oldVal);
+    }
+    assertEquals("Sanity check test", sizeCounted, totalAllocated.get());
+    
+    // Now check each byte array to make sure allocations don't overlap
+    for (Map<Integer, AllocRecord> allocsInChunk : mapsByChunk.values()) {
+      int expectedOff = 0;
+      for (AllocRecord alloc : allocsInChunk.values()) {
+        assertEquals(expectedOff, alloc.alloc.getOffset());
+        assertTrue("Allocation " + alloc + " overruns buffer",
+            alloc.alloc.getOffset() + alloc.size <= 
alloc.alloc.getData().length);
+        expectedOff += alloc.size;
+      }
+    }
+
+  }
+  
+  private static class AllocRecord implements Comparable<AllocRecord>{
+    private final Allocation alloc;
+    private final int size;
+    public AllocRecord(Allocation alloc, int size) {
+      super();
+      this.alloc = alloc;
+      this.size = size;
+    }
+
+    @Override
+    public int compareTo(AllocRecord e) {
+      if (alloc.getData() != e.alloc.getData()) {
+        throw new RuntimeException("Can only compare within a particular 
array");
+      }
+      return Ints.compare(alloc.getOffset(), e.alloc.getOffset());
+    }
+    
+    @Override
+    public String toString() {
+      return "AllocRecord(alloc=" + alloc + ", size=" + size + ")";
+    }
+    
+  }
+}


Reply via email to