Package com.danga.MemCached
Class NativeHandler
java.lang.Object
com.danga.MemCached.NativeHandler
Handle encoding standard Java types directly which can result in significant
memory savings:
Currently the Memcached driver for Java supports the setSerialize() option.
This can increase performance in some situations but has a few issues:
Code that performs class casting will throw ClassCastExceptions when
setSerialize is enabled. For example:
mc.set( "foo", new Integer( 1 ) ); Integer output = (Integer)mc.get("foo");
Will work just file when setSerialize is true but when its false will just throw
a ClassCastException.
Also internally it doesn't support Boolean and since toString is called wastes a
lot of memory and causes additional performance issue. For example an Integer
can take anywhere from 1 byte to 10 bytes.
Due to the way the memcached slab allocator works it seems like a LOT of wasted
memory to store primitive types as serialized objects (from a performance and
memory perspective). In our applications we have millions of small objects and
wasted memory would become a big problem.
For example a Serialized Boolean takes 47 bytes which means it will fit into the
64byte LRU. Using 1 byte means it will fit into the 8 byte LRU thus saving 8x
the memory. This also saves the CPU performance since we don't have to
serialize bytes back and forth and we can compute the byte[] value directly.
One problem would be when the user calls get() because doing so would require
the app to know the type of the object stored as a bytearray inside memcached
(since the user will probably cast).
If we assume the basic types are interned we could use the first byte as the
type with the remaining bytes as the value. Then on get() we could read the
first byte to determine the type and then construct the correct object for it.
This would prevent the ClassCastException I talked about above.
We could remove the setSerialize() option and just assume that standard VM types
are always internd in this manner.
mc.set( "foo", new Boolean.TRUE ); Boolean b = (Boolean)mc.get( "foo" );
And the type casts would work because internally we would create a new Boolean
to return back to the client.
This would reduce memory footprint and allow for a virtual implementation of the
Externalizable interface which is much faster than Serialzation.
Currently the memory improvements would be:
java.lang.Boolean - 8x performance improvement (now just two bytes)
java.lang.Integer - 16x performance improvement (now just 5 bytes)
Most of the other primitive types would benefit from this optimization.
java.lang.Character being another obvious example.
I know it seems like I'm being really picky here but for our application I'd
save 1G of memory right off the bat. We'd go down from 1.152G of memory used
down to 144M of memory used which is much better IMO.
http://java.sun.com/docs/books/tutorial/native1.1/integrating/types.html
- Author:
- Kevin A. Burton, Greg Whalin <greg@meetup.com>
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic Object
decode
(byte[] b, int flag) Decodes byte array using memcache flag to determine type.protected static Boolean
decodeBoolean
(byte[] b) protected static Byte
decodeByte
(byte[] b) protected static byte[]
decodeByteArr
(byte[] b) protected static Character
decodeCharacter
(byte[] b) protected static Date
decodeDate
(byte[] b) protected static Double
decodeDouble
(byte[] b) protected static Float
decodeFloat
(byte[] b) protected static Integer
decodeInteger
(byte[] b) protected static Long
decodeLong
(byte[] b) protected static Short
decodeShort
(byte[] b) protected static String
decodeString
(byte[] b) protected static StringBuffer
decodeStringBuffer
(byte[] b) protected static StringBuilder
decodeStringBuilder
(byte[] b) protected static byte[]
encode
(byte[] value) protected static byte[]
encode
(double value) protected static byte[]
encode
(float value) protected static byte[]
encode
(int value) protected static byte[]
encode
(long value) protected static byte[]
protected static byte[]
protected static byte[]
static byte[]
Encodes supported typesprotected static byte[]
protected static byte[]
protected static byte[]
encode
(StringBuffer value) protected static byte[]
encode
(StringBuilder value) protected static byte[]
protected static byte[]
getBytes
(int value) protected static byte[]
getBytes
(long value) static int
getMarkerFlag
(Object value) Returns the flag for marking the type of the byte array.static boolean
Detemine of object can be natively serialized by this class.protected static int
toInt
(byte[] b) This works by taking each of the bit patterns and converting them to ints taking into account 2s complement and then adding them..protected static long
toLong
(byte[] b)
-
Field Details
-
log
private static org.apache.log4j.Logger log
-
-
Constructor Details
-
NativeHandler
public NativeHandler()
-
-
Method Details
-
isHandled
Detemine of object can be natively serialized by this class.- Parameters:
value
- Object to test.- Returns:
- true/false
-
getMarkerFlag
Returns the flag for marking the type of the byte array.- Parameters:
value
- Object we are storing.- Returns:
- int marker
-
encode
Encodes supported types- Parameters:
value
- Object to encode.- Returns:
- byte array
- Throws:
Exception
- If fail to encode.
-
encode
-
encode
-
encode
protected static byte[] encode(int value) -
encode
- Throws:
Exception
-
encode
-
encode
-
encode
- Throws:
Exception
-
encode
- Throws:
Exception
-
encode
- Throws:
Exception
-
encode
- Throws:
Exception
-
encode
- Throws:
Exception
-
encode
- Throws:
Exception
-
encode
protected static byte[] encode(byte[] value) -
getBytes
protected static byte[] getBytes(long value) -
getBytes
protected static byte[] getBytes(int value) -
decode
Decodes byte array using memcache flag to determine type.- Parameters:
b
-marker
-- Returns:
- Throws:
Exception
-
decodeByte
-
decodeBoolean
-
decodeInteger
-
decodeLong
- Throws:
Exception
-
decodeCharacter
-
decodeString
- Throws:
Exception
-
decodeStringBuffer
- Throws:
Exception
-
decodeFloat
- Throws:
Exception
-
decodeShort
- Throws:
Exception
-
decodeDouble
- Throws:
Exception
-
decodeDate
-
decodeStringBuilder
- Throws:
Exception
-
decodeByteArr
protected static byte[] decodeByteArr(byte[] b) -
toInt
protected static int toInt(byte[] b) This works by taking each of the bit patterns and converting them to ints taking into account 2s complement and then adding them..- Parameters:
b
-- Returns:
-
toLong
protected static long toLong(byte[] b)
-