You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tv...@apache.org on 2014/01/06 18:40:00 UTC

svn commit: r1555939 - in /commons/proper/jcs/trunk/src: changes/changes.xml java/org/apache/commons/jcs/auxiliary/disk/block/BlockDisk.java

Author: tv
Date: Mon Jan  6 17:40:00 2014
New Revision: 1555939

URL: http://svn.apache.org/r1555939
Log:
JCS-109: Improve performance of BlockDisk.write(Serializable)

Modified:
    commons/proper/jcs/trunk/src/changes/changes.xml
    commons/proper/jcs/trunk/src/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDisk.java

Modified: commons/proper/jcs/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/changes/changes.xml?rev=1555939&r1=1555938&r2=1555939&view=diff
==============================================================================
--- commons/proper/jcs/trunk/src/changes/changes.xml (original)
+++ commons/proper/jcs/trunk/src/changes/changes.xml Mon Jan  6 17:40:00 2014
@@ -20,6 +20,9 @@
 	</properties>
 	<body>
 		<release version="2.0" date="unreleased" description="JDK 1.5 based major release">
+            <action dev="tv" type="update" issue="JCS-109" due-to="Xiong LIU">
+                Improve performance of BlockDisk.write(Serializable)
+            </action>
             <action dev="tv" type="fix" issue="JCS-102" due-to="Robert Clark">
                 Reworked the interfaces to make the group cache typesafe
             </action>

Modified: commons/proper/jcs/trunk/src/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDisk.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDisk.java?rev=1555939&r1=1555938&r2=1555939&view=diff
==============================================================================
--- commons/proper/jcs/trunk/src/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDisk.java (original)
+++ commons/proper/jcs/trunk/src/java/org/apache/commons/jcs/auxiliary/disk/block/BlockDisk.java Mon Jan  6 17:40:00 2014
@@ -48,7 +48,7 @@ public class BlockDisk
     private static final Log log = LogFactory.getLog( BlockDisk.class );
 
     /** The size of the header that indicates the amount of data stored in an occupied block. */
-    public static final byte HEADER_SIZE_BYTES = 4; 
+    public static final byte HEADER_SIZE_BYTES = 4;
     // N.B. 4 bytes is the size used for ByteBuffer.putInt(int value) and ByteBuffer.getInt()
 
     /** defaults to 4kb */
@@ -132,6 +132,31 @@ public class BlockDisk
     }
 
     /**
+     * Allocate a given number of blocks from the available set
+     *
+     * @param numBlocksNeeded
+     * @return an array of allocated blocks
+     */
+    private int[] allocateBlocks(int numBlocksNeeded)
+    {
+        assert numBlocksNeeded >= 1;
+
+        int[] blocks = new int[numBlocksNeeded];
+        // get them from the empty list or take the next one
+        for (int i = 0; i < numBlocksNeeded; i++)
+        {
+            Integer emptyBlock = emptyBlocks.takeFirst();
+            if (emptyBlock == null)
+            {
+                emptyBlock = numberOfBlocks.getAndIncrement();
+            }
+            blocks[i] = emptyBlock;
+        }
+
+        return blocks;
+    }
+
+    /**
      * This writes an object to disk and returns the blocks it was stored in.
      * <p>
      * The program flow is as follows:
@@ -152,7 +177,7 @@ public class BlockDisk
         throws IOException
     {
         // serialize the object
-        byte[] data = elementSerializer.serialize( object );
+        byte[] data = elementSerializer.serialize(object);
 
         if ( log.isDebugEnabled() )
         {
@@ -163,38 +188,43 @@ public class BlockDisk
         this.putCount.incrementAndGet();
 
         // figure out how many blocks we need.
-        int numBlocksNeeded = calculateTheNumberOfBlocksNeeded( data );
+        int numBlocksNeeded = calculateTheNumberOfBlocksNeeded(data);
+
         if ( log.isDebugEnabled() )
         {
             log.debug( "numBlocksNeeded = " + numBlocksNeeded );
         }
 
-        int[] blocks = new int[numBlocksNeeded];
+        // allocate blocks
+        int[] blocks = allocateBlocks(numBlocksNeeded);
 
-        // get them from the empty list or take the next one
-        for ( int i = 0; i < numBlocksNeeded; i++ )
+        int offset = 0;
+        final int maxChunkSize = blockSizeBytes - HEADER_SIZE_BYTES;
+        ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_SIZE_BYTES);
+
+        for (int i = 0; i < numBlocksNeeded; i++)
         {
-            Integer emptyBlock = emptyBlocks.takeFirst();
-            if ( emptyBlock != null )
-            {
-                blocks[i] = emptyBlock.intValue();
-            }
-            else
-            {
-                blocks[i] = this.numberOfBlocks.getAndIncrement();
-            }
-        }
+            headerBuffer.clear();
+            int length = Math.min(maxChunkSize, data.length - offset);
+            headerBuffer.putInt(length);
 
-        // get the individual sub arrays.
-        byte[][] chunks = getBlockChunks( data, numBlocksNeeded );
+            ByteBuffer dataBuffer = ByteBuffer.wrap(data, offset, length);
 
-        // write the blocks
-        for ( int i = 0; i < numBlocksNeeded; i++ )
-        {
-            int position = calculateByteOffsetForBlock( blocks[i] );
-            write( position, chunks[i] );
+            long position = calculateByteOffsetForBlock(blocks[i]);
+            // write the header
+            headerBuffer.flip();
+            int written = fc.write(headerBuffer, position);
+            assert written == HEADER_SIZE_BYTES;
+
+            //write the data
+            written = fc.write(dataBuffer, position + HEADER_SIZE_BYTES);
+            assert written == length;
+
+            offset += length;
         }
 
+        fc.force(false);
+
         return blocks;
     }
 
@@ -236,27 +266,6 @@ public class BlockDisk
     }
 
     /**
-     * Writes the given byte array to the Disk at the specified position.
-     * <p>
-     * @param position
-     * @param data
-     * @return true if we wrote successfully
-     * @throws IOException
-     */
-    private boolean write( long position, byte[] data )
-        throws IOException
-    {
-        ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE_BYTES + data.length);
-        buffer.putInt(data.length);
-        buffer.put(data);
-        buffer.flip();
-        int written = fc.write(buffer, position);
-        fc.force(true);
-
-        return written == data.length + HEADER_SIZE_BYTES;
-    }
-
-    /**
      * Reads an object that is located in the specified blocks.
      * <p>
      * @param blockNumbers