Created
December 17, 2011 14:00
-
-
Save ngocdaothanh/1490276 to your computer and use it in GitHub Desktop.
ByteBuffer.allocateDirect vs Unsafe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Benchmark { | |
private val LOOP_COUNT = 1000000 | |
private val ARRAY_SIZE = 1024 | |
def main(args: Array[String]) { | |
val t1 = System.currentTimeMillis | |
var i = 0 | |
while (i < LOOP_COUNT) { | |
testDirectByteBuffer | |
//testUnsafeMemory | |
i += 1 | |
} | |
val t2 = System.currentTimeMillis | |
println("" + (t2 - t1) + " [ms]") | |
} | |
private def testDirectByteBuffer { | |
val b = java.nio.ByteBuffer.allocateDirect(ARRAY_SIZE) | |
b.put(new Array[Byte](ARRAY_SIZE)) | |
//DirectByteBufferCleaner.clean(b) | |
} | |
private def testUnsafeMemory { | |
val m = UnsafeMemory.allocate(new Array[Byte](ARRAY_SIZE)) | |
//assert(m.bytes.length == ARRAY_SIZE) | |
m.free() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.ByteBuffer | |
/** | |
* Frees memory of direct buffer allocated by ByteBuffer.allocateDirect | |
* without waiting for GC. | |
* | |
* See: | |
* http://groups.google.com/group/netty/browse_thread/thread/3be7f573384af977 | |
* https://github.com/netty/netty/issues/62 | |
*/ | |
object DirectByteBufferCleaner { | |
private val cleanerMethod = { | |
val klass = Class.forName("java.nio.DirectByteBuffer") | |
val ret = klass.getDeclaredMethod("cleaner") | |
ret.setAccessible(true) | |
ret | |
} | |
private val cleanMethod = { | |
val klass = Class.forName("sun.misc.Cleaner") | |
klass.getDeclaredMethod("clean") | |
} | |
def clean(directByteBuffer: ByteBuffer) { | |
val cleaner = cleanerMethod.invoke(directByteBuffer) | |
cleanMethod.invoke(cleaner) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sun.misc.Unsafe | |
import java.lang.{Long => JLong} | |
// See http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/io/util/Memory.java?view=markup | |
object UnsafeMemory { | |
val unsafe = { | |
val field = classOf[Unsafe].getDeclaredField("theUnsafe") | |
field.setAccessible(true) | |
field.get(null).asInstanceOf[Unsafe] | |
} | |
// Newer? | |
// http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/nio/Bits.java | |
val copyFromByteArray = { | |
try { | |
val klass = Class.forName("java.nio.Bits") | |
val method = klass.getDeclaredMethod("copyFromByteArray", classOf[Object], JLong.TYPE, JLong.TYPE, JLong.TYPE) | |
method.setAccessible(true) | |
method | |
} catch { | |
case _ => null | |
} | |
} | |
// Older? | |
// http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/nio/Bits.java.html | |
val copyFromArray = { | |
try { | |
val klass = Class.forName("java.nio.Bits") | |
val method = klass.getDeclaredMethod("copyFromArray", classOf[Object], JLong.TYPE, JLong.TYPE, JLong.TYPE, JLong.TYPE) | |
method.setAccessible(true) | |
method | |
} catch { | |
case _ => null | |
} | |
} | |
def copyFromByteArray(bytes: Array[Byte], dst: Long) { | |
/* | |
val size = bytes.length | |
var offset = 0 | |
while (offset < size) { | |
unsafe.putByte(dst + offset, bytes(offset)) | |
offset += 1 | |
} | |
*/ | |
if (copyFromByteArray != null) | |
copyFromByteArray.invoke(null, bytes, new JLong(0), new JLong(dst), new JLong(bytes.length)) | |
else | |
copyFromArray.invoke(null, bytes, new JLong(16), new JLong(0), new JLong(dst), new JLong(bytes.length)) | |
} | |
/** Transfers bytes to unsafe memory. */ | |
def allocate(bytes: Array[Byte]): UnsafeMemory = { | |
val size = bytes.length // Int | |
val peer = unsafe.allocateMemory(size) | |
copyFromByteArray(bytes, peer) | |
new UnsafeMemory(peer, size) | |
} | |
} | |
class UnsafeMemory(private var peer: Long, size: Int) { | |
import UnsafeMemory.unsafe | |
// Newer? | |
// http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/nio/Bits.java | |
val copyToByteArray = { | |
try { | |
val klass = Class.forName("java.nio.Bits") | |
val method = klass.getDeclaredMethod("copyToByteArray", JLong.TYPE, classOf[Object], JLong.TYPE, JLong.TYPE) | |
method.setAccessible(true) | |
method | |
} catch { | |
case _ => null | |
} | |
} | |
// Older? | |
// http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/nio/Bits.java.html | |
val copyToArray = { | |
try { | |
val klass = Class.forName("java.nio.Bits") | |
val method = klass.getDeclaredMethod("copyToArray", JLong.TYPE, classOf[Object], JLong.TYPE, JLong.TYPE, JLong.TYPE) | |
method.setAccessible(true) | |
method | |
} catch { | |
case _ => null | |
} | |
} | |
def copyToByteArray(src: Long, bytes: Array[Byte]) { | |
/* | |
val size = bytes.length | |
var offset = 0 | |
while (offset < size) { | |
ret(offset) = unsafe.getByte(src + offset) | |
offset += 1 | |
} | |
*/ | |
if (copyToByteArray != null) | |
copyToByteArray.invoke(null, new JLong(src), bytes, new JLong(0), new JLong(bytes.length)) | |
else | |
copyToArray.invoke(null, new JLong(src), bytes, new JLong(16), new JLong(0), new JLong(bytes.length)) | |
} | |
/** Transfers unsafe memory to bytes. */ | |
def bytes = { | |
if (peer == 0) throw new NullPointerException("Unsafe memory has been freed") | |
val ret = new Array[Byte](size) | |
copyToByteArray(peer, ret) | |
ret | |
} | |
def free() { | |
if (peer != 0) { | |
unsafe.freeMemory(peer) | |
peer = 0 | |
} | |
} | |
override protected def finalize() { | |
try { | |
free() | |
} finally { | |
super.finalize() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
please paste results?