Address: http://x-rip.iteye.com/blog/1555344
Kryo is a fast and efficient Java object graphics serialization framework. It supports Java and is better than Google's famous serialization framework protobuf in Java serialization. Because protobuf needs to write the schema file (. PROTO), and static compilation is required. Therefore, compare the serialization framework Hessian similar to kryo to find out why kryo is so fast.
There are three main indicators in the serialization process:
1. Object serialized size
An object is serialized as a byte array by a serialization tool, which contains the field value and metadata information of the object so that it can be deserialized back to an object.
2. serialization and deserialization speed
The time when an object is serialized into a byte array depends on the method by which it generates/parses the byte array.
3. serialization tool speed
The creation of the serialization tool itself will consume a certain amount.
Start with the serialized size:
Test class:
public class Simple implements java.io.Serializable{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } static Simple getSimple() { Simple simple = new Simple(); simple.setAge(10); simple.setName("XiaoMing"); return simple; }}
Kryo serialization:
Kryo kryo = new Kryo(); kryo.setReferences(false); kryo.setRegistrationRequired(false); kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); output.setOutputStream(new FileOutputStream("file.bin")); kryo.writeClassAndObject(output, Simple.getSimple()); output.flush();
View the serialized results:
Red part: object header. 01 00 indicates an unregistered class.
Black part: the name of the class to which the object belongs (kryo does not set the end character of a field. For a byte array of an indefinite length such as string, kryo will add the in its last byte, for example, if the last digit of the class name is e and its askii code is X65, the class is added to the base of the class, that is, the class is E5)
Green: indicates the ID of the object in the object graph. That is, the ID of the simple object in the object graph is 01.
The blue part indicates the field of the class. 14 In 02 14 indicates the int value 10 (The ing relationship is shown in Table 1). 02 and 01 in the green part mean the same. That is, the ID of the int object 10 in the object graph is 02. Similarly, 03 indicates the third object in the object graph, that is, the string Xiaoming. Similarly, the last byte is added to the client.
Hessian serialization:
HessianOutput hout = new HessianOutput(new FileOutputStream("hessian.bin")); hout.writeObject(Simple.getSimple());
View the serialized results:
Red part: Object Header
Black part: Class Name of the object (askii code of the class name)
Purple: byte type descriptor, indicating the type of the subsequent bytes, 53 indicates string, 49 indicates int, and so on.
Green part: Byte Length descriptor, used to indicate the number of bytes that follow this Byte Group
White part: actual byte value of Field Type
Blue: the actual value of filed
7A: Terminator
We can see the following points from the serialized Bytes:
1. kryo is much smaller than Hessian after serialization. (Kryo is better than Hessian)
2. Because kryo does not serialize the description of the field class, kryo needs to load the filed of the class by itself. This means that if the class is not registered in kryo, or the class is first serialized by kryo, kryo needs time to load the class (Hessian is better than kryo)
3. For the reason of 2, if the class has been loaded by kryo, then kryo saves the class information and can quickly enter the byte array into the class field, hessian needs to parse the field information in the serialized byte array. For serialized classes, kryo is better than Hessian.
4. Hessian uses a fixed length to store int and long, while kryo uses a variable length. In reality, a large amount of data will not appear frequently. (Kryo is better than Hessian)
5. Hessian writes the serialized field length to determine the end of a field, while kryo uses the last byte + cross (kryo is better than Hessian) for the end of a string)
In summary:
To ensure the serialization efficiency, kryo loads the classes to be serialized, which consumes a certain amount. It can be understood as the consumption of kryo itself. This consumption ensures that the size after serialization (avoiding unnecessary source data) is small and fast deserialization.
Ensure that this basic data type is as small as possible after serialization through the variable length int and long values
Mark the field range through the last special operation rather than the write length.
Not covered in this article are:
Use the open-source tool reflectasm for reflection instead of Java reflection
Use objenesis to create objects of classes without default constructor
Kryo currently only supports Java, so the official documentation does not provide the kryo grammer used for serialization. By default, the following 10 types are supported. See table 1.
Table 1:
# the number of milliseconds since January 1, 1970, 00:00:00 GMTdate ::= x01 x00 <the number of milliseconds since January 1, 1970, 00:00:00 GMT> # boolean true/falseboolean ::= x02 x01# true ::= x02 x00# false # 8-bit binary databyte ::= x03 <binary-data># binary-data # charchar ::= x04 x00 <binary-data># binary-data # shortshort ::= x05 [x00-x7F] [x01-xFF]# 0 to 32767 ::= x05 [x80-xFF] [x01-xFF]# -23768 to -1 # 32-bit signed integer( + x02 when increment)int ::= x06 x01 [x00-x7E]# 0 to 63 ::= x06 x01 [x80-x9E] [x04-xFF] # 64 to 4095 ::= x06 x01 [xA0-xBE] [x00-xFF] [x01-xFF] # 4096 to 1048575 ::= x06 x01 [xC0-xDE] [x00-xFF] [x00-xFF] [x01-xFF] # 1048576 to 268435455 ::= x06 x01 [xE0-xFE] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x07] # 268435456 to 2147483647 ::= x06 x01 [x01-x7F]# -1 to -64 ::= x06 x01 [x81-x9F] [x04-xFF] # -65 to -4096 ::= x06 x01 [xA1-xBF] [x00-xFF] [x01-xFF] # -4097 to -1048576 ::= x06 x01 [xC1-xDF] [x00-xFF] [x00-xFF] [x01-xFF] # -1048577 to -268435456 ::= x06 x01 [xE1-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x07] # -268435457 to -2147483648 # 64-bit signed long integer ( +x02 when incerment)long ::= x07 x01 [x00-x7E]# 0 to 63 ::= x07 x01 [x80-x8E] [x08-xFF] # 64 to 2047 ::= x07 x01 [x90-x9E] [x00-xFF] [x01-xFF] # 2048 to 524287 ::= x07 x01 [xA0-xAE] [x00-xFF] [x00-xFF] [x01-xFF] # 524288 to 134217727 ::= x07 x01 [xB0-xBE] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 134217728 to 34359738367 ::= x07 x01 [xC0-xCE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 34359738368 to 8796093022207 ::= x07 x01 [xD0-xDE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 8796093022208 to 2251799813685247 ::= x07 x01 [xE0-xEE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # 2251799813685248 to 576460752303423487 ::= x07 x01 [xF0-xFE] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x0F] # 576460752303423488 to 9223372036854775807 ::= x07 x01 [x01-x7F]# -1 to -64 ::= x07 x01 [x81-x8F] [x08-xFF] # -65 to -2048 ::= x07 x01 [x91-x9F] [x00-xFF] [x01-xFF] # -2049 to -524288 ::= x07 x01 [xA1-xAF] [x00-xFF] [x00-xFF] [x01-xFF] # -524289 to -134217728 ::= x07 x01 [xB1-xBF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # -134217729 to -34359738368 ::= x07 x01 [xC1-xCF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # -34359738369 to -8796093022208 ::= x07 x01 [xD1-xDF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # -8796093022209 to -2251799813685248 ::= x07 x01 [xE1-xEF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-xFF] # -2251799813685249 to -576460752303423488 ::= x07 x01 [xF1-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x00-xFF] [x01-x0F] # -576460752303423489 to -9223372036854775808 # float/Floatfloat ::= x08 x01 <floatToInt> # double/Doubledouble ::= x09 x01 <doubleToLong> # StringString ::= x0A x01 x82 <utf8-data># data.length()=1 ::= x0A x01 <utf8-data.subString(0,data.length()-2)> <utf8-data.charAt(data.length-1)>+x70# data.length()>1 # The class not registered in kryoObject::= x01 x00 <(string)className> <(byte)id> <(Object)objectFieldValue ordered by fieldName>