From 1286bdde2259a773fe148940948c78d5c9c89353 Mon Sep 17 00:00:00 2001
From: Peter Lawrey <peter.lawrey@higherfrequencytrading.com>
Date: Sun, 31 Jul 2016 20:32:43 +0100
Subject: [PATCH] Optimise fillBytesImpl so it doesn't trigger an Exception on
 every byte[] generated. (#815)

* Optimise fillBytesImpl so it doesn't trigger an Exception on every byte[] generated.

* Make the verbose output of BasicDB thread safe.

* Optimise the verbose output of BasicDB when using multiple threads
---
 .../src/main/java/com/yahoo/ycsb/BasicDB.java | 59 +++++++++++++------
 .../com/yahoo/ycsb/RandomByteIterator.java    | 25 +++++---
 2 files changed, 58 insertions(+), 26 deletions(-)

diff --git a/core/src/main/java/com/yahoo/ycsb/BasicDB.java b/core/src/main/java/com/yahoo/ycsb/BasicDB.java
index 83eb5e25..ec12bcda 100644
--- a/core/src/main/java/com/yahoo/ycsb/BasicDB.java
+++ b/core/src/main/java/com/yahoo/ycsb/BasicDB.java
@@ -80,7 +80,7 @@ public class BasicDB extends DB
 		verbose=Boolean.parseBoolean(getProperties().getProperty(VERBOSE, VERBOSE_DEFAULT));
 		todelay=Integer.parseInt(getProperties().getProperty(SIMULATE_DELAY, SIMULATE_DELAY_DEFAULT));
 		randomizedelay=Boolean.parseBoolean(getProperties().getProperty(RANDOMIZE_DELAY, RANDOMIZE_DELAY_DEFAULT));
-		if (verbose)
+		if (verbose) synchronized(System.out)
 		{
 			System.out.println("***************** properties *****************");
 			Properties p=getProperties();
@@ -96,6 +96,19 @@ public class BasicDB extends DB
 		}
 	}
 
+  static final ThreadLocal<StringBuilder>  TL_STRING_BUILDER = new ThreadLocal<StringBuilder>() {
+    @Override
+    protected StringBuilder initialValue() {
+      return new StringBuilder();
+    }
+  };
+
+  static StringBuilder getStringBuilder() {
+    StringBuilder sb = TL_STRING_BUILDER.get();
+    sb.setLength(0);
+    return sb;
+  }
+
 	/**
 	 * Read a record from the database. Each field/value pair from the result will be stored in a HashMap.
 	 *
@@ -111,21 +124,23 @@ public class BasicDB extends DB
 
 		if (verbose)
 		{
-			System.out.print("READ "+table+" "+key+" [ ");
+      StringBuilder sb = getStringBuilder();
+			sb.append("READ ").append(table).append(" ").append(key).append(" [ ");
 			if (fields!=null)
 			{
 				for (String f : fields)
 				{
-					System.out.print(f+" ");
+          sb.append(f).append(" ");
 				}
 			}
 			else
 			{
-				System.out.print("<all fields>");
+        sb.append("<all fields>");
 			}
 
-			System.out.println("]");
-		}
+      sb.append("]");
+      System.out.println(sb);
+    }
 
 		return Status.OK;
 	}
@@ -146,21 +161,23 @@ public class BasicDB extends DB
 
 		if (verbose)
 		{
-			System.out.print("SCAN "+table+" "+startkey+" "+recordcount+" [ ");
+      StringBuilder sb = getStringBuilder();
+      sb.append("SCAN ").append(table).append(" ").append(startkey).append(" ").append(recordcount).append(" [ ");
 			if (fields!=null)
 			{
 				for (String f : fields)
 				{
-					System.out.print(f+" ");
+          sb.append(f).append(" ");
 				}
 			}
 			else
 			{
-				System.out.print("<all fields>");
+        sb.append("<all fields>");
 			}
 
-			System.out.println("]");
-		}
+      sb.append("]");
+      System.out.println(sb);
+    }
 
 		return Status.OK;
 	}
@@ -180,15 +197,17 @@ public class BasicDB extends DB
 
 		if (verbose)
 		{
-			System.out.print("UPDATE "+table+" "+key+" [ ");
+      StringBuilder sb = getStringBuilder();
+      sb.append("UPDATE ").append(table).append(" ").append(key).append(" [ ");
 			if (values!=null)
 			{
 				for (Map.Entry<String, ByteIterator> entry : values.entrySet())
 				{
-					System.out.print(entry.getKey() +"="+ entry.getValue() +" ");
+          sb.append(entry.getKey()).append("=").append(entry.getValue()).append(" ");
 				}
 			}
-			System.out.println("]");
+      sb.append("]");
+      System.out.println(sb);
 		}
 
 		return Status.OK;
@@ -209,16 +228,18 @@ public class BasicDB extends DB
 
 		if (verbose)
 		{
-			System.out.print("INSERT "+table+" "+key+" [ ");
+      StringBuilder sb = getStringBuilder();
+      sb.append("INSERT ").append(table).append(" ").append(key).append(" [ ");
 			if (values!=null)
 			{
 				for (Map.Entry<String, ByteIterator> entry : values.entrySet())
 				{
-					System.out.print(entry.getKey() +"="+ entry.getValue() +" ");
+          sb.append(entry.getKey()).append("=").append(entry.getValue()).append(" ");
 				}
 			}
 
-			System.out.println("]");
+      sb.append("]");
+      System.out.println(sb);
 		}
 
 		return Status.OK;
@@ -238,7 +259,9 @@ public class BasicDB extends DB
 
 		if (verbose)
 		{
-			System.out.println("DELETE "+table+" "+key);
+      StringBuilder sb = getStringBuilder();
+      sb.append("DELETE ").append(table).append(" ").append(key);
+      System.out.println(sb);
 		}
 
 		return Status.OK;
diff --git a/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java b/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java
index cb0977aa..b080ec56 100644
--- a/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java
+++ b/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java
@@ -32,14 +32,23 @@ public class RandomByteIterator extends ByteIterator {
 
   private void fillBytesImpl(byte[] buffer, int base) {
     int bytes = Utils.random().nextInt();
-    try {
-      buffer[base+0] = (byte)(((bytes) & 31) + ' ');
-      buffer[base+1] = (byte)(((bytes >> 5) & 63) + ' ');
-      buffer[base+2] = (byte)(((bytes >> 10) & 95) + ' ');
-      buffer[base+3] = (byte)(((bytes >> 15) & 31) + ' ');
-      buffer[base+4] = (byte)(((bytes >> 20) & 63) + ' ');
-      buffer[base+5] = (byte)(((bytes >> 25) & 95) + ' ');
-    } catch (ArrayIndexOutOfBoundsException e) { /* ignore it */ }
+
+    switch(buffer.length - base) {
+      default:
+        buffer[base+5] = (byte)(((bytes >> 25) & 95) + ' ');
+      case 5:
+        buffer[base+4] = (byte)(((bytes >> 20) & 63) + ' ');
+      case 4:
+        buffer[base+3] = (byte)(((bytes >> 15) & 31) + ' ');
+      case 3:
+        buffer[base+2] = (byte)(((bytes >> 10) & 95) + ' ');
+      case 2:
+        buffer[base+1] = (byte)(((bytes >> 5) & 63) + ' ');
+      case 1:
+        buffer[base+0] = (byte)(((bytes) & 31) + ' ');
+      case 0:
+        break;
+    }
   }
 
   private void fillBytes() {
-- 
GitLab