仍然和 fury 有明显的性能差距,从数组的数据写入的角度尝试优化

master
linbin 2024-04-12 03:22:44 +08:00
parent 81f0e22d76
commit 1714fbd246
12 changed files with 1443 additions and 111 deletions

38
pom.xml
View File

@ -2,7 +2,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<groupId>com.jfirer</groupId>
<artifactId>JfireSE</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
@ -13,7 +13,18 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<distributionManagement>
<repository>
<id>nexus3</id>
<name>nexus</name>
<url>http://yynas.cn:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus3</id>
<name>nexus</name>
<url>http://yynas.cn:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
@ -32,6 +43,29 @@
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jfirer</groupId>
<artifactId>Fse</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.furyio</groupId>
<artifactId>fury-core</artifactId>
<version>0.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -13,7 +13,8 @@ public class ClassInfo
private String className;
private Serializer serializer;
private JfireSE jfireSE;
private Object[] refTracking;
private Object[] tracking;
private boolean refTracking;
private int refTrackingIndex = 0;
public void writeBytes(InternalByteArray byteArray, Object instance, boolean knownClazz)
@ -29,7 +30,7 @@ public class ClassInfo
}
if (knownClazz)
{
if (jfireSE.isCycleSupport())
if (refTracking)
{
int tracking = addTracking(instance);
if (tracking == -1)
@ -53,7 +54,7 @@ public class ClassInfo
}
else
{
if (jfireSE.isCycleSupport())
if (refTracking)
{
if (classId == ClassInfoResolver.NO_CLASS_ID)
{
@ -101,32 +102,65 @@ public class ClassInfo
}
}
public void reset()
public void reset(int tempClassIdStart)
{
classId = ClassInfoResolver.NO_CLASS_ID;
if (classId < tempClassIdStart)
{
;
}
else
{
classId = ClassInfoResolver.NO_CLASS_ID;
}
refTrackingIndex = 0;
}
public int addTracking(Object instance)
{
if (refTracking == null)
if (tracking == null)
{
refTracking = new Object[4];
tracking = new Object[4];
}
for (int i = 0; i < refTrackingIndex; i++)
{
if (refTracking[i] == instance)
if (tracking[i] == instance)
{
return i;
}
}
if (refTrackingIndex == refTracking.length)
if (refTrackingIndex == tracking.length)
{
Object[] newRefTracking = new Object[refTracking.length * 2];
System.arraycopy(refTracking, 0, newRefTracking, 0, refTracking.length);
refTracking = newRefTracking;
Object[] newRefTracking = new Object[tracking.length * 2];
System.arraycopy(tracking, 0, newRefTracking, 0, tracking.length);
tracking = newRefTracking;
}
refTracking[refTrackingIndex++] = instance;
tracking[refTrackingIndex++] = instance;
return -1;
}
/**
* 3
*
* @param byteArray
* @param refTracking
* @return
*/
public Object readBytes(InternalByteArray byteArray, boolean refTracking)
{
if (serializer == null)
{
serializer = jfireSE.getSerializer(clazz);
}
Object instance = serializer.readBytes(byteArray);
if (refTracking)
{
addTracking(instance);
}
return instance;
}
public Object getTracking(int instanceId)
{
return tracking[instanceId];
}
}

View File

@ -1,46 +1,59 @@
package com.jfirer.se;
import com.jfirer.se.serializer.SerializerResolver;
import java.util.IdentityHashMap;
import java.util.Map;
public class ClassInfoResolver
{
public static int NO_CLASS_ID = 0;
private Map<Class, ClassInfo> store = new IdentityHashMap<>();
private int currentClassId = 1;
private int fixedClassId = 1;
private ClassInfo[] tracking = new ClassInfo[32];
public static int NO_CLASS_ID = 0;
private Map<Class, ClassInfo> store = new IdentityHashMap<>();
private int nextClassId = 1;
private int tempClassIdStart = 1;
private ClassInfo[] tracking = new ClassInfo[32];
private JfireSE jfireSE;
private SerializerResolver resolver;
public ClassInfoResolver(SerializerResolver resolver, JfireSE jfireSE)
public ClassInfoResolver(JfireSE jfireSE)
{
this.resolver = resolver;
this.jfireSE = jfireSE;
this.jfireSE = jfireSE;
registerClass(int[].class);
registerClass(long[].class);
registerClass(short[].class);
registerClass(float[].class);
registerClass(double[].class);
registerClass(char[].class);
registerClass(boolean[].class);
registerClass(byte[].class);
registerClass(String[].class);
registerClass(Integer[].class);
registerClass(Long[].class);
registerClass(Short[].class);
registerClass(Float[].class);
registerClass(Double[].class);
registerClass(Character[].class);
registerClass(Boolean[].class);
registerClass(Byte[].class);
}
public void getClassId(ClassInfo classInfo)
{
if (currentClassId > tracking.length)
if (nextClassId > tracking.length)
{
ClassInfo[] newTracking = new ClassInfo[tracking.length << 1];
System.arraycopy(tracking, 0, newTracking, 0, tracking.length);
tracking = newTracking;
}
tracking[currentClassId] = classInfo;
classInfo.setClassId(currentClassId);
currentClassId += 1;
tracking[nextClassId] = classInfo;
classInfo.setClassId(nextClassId);
nextClassId += 1;
}
public void reset()
{
for (int i = currentClassId - 1; i > fixedClassId; i--)
for (int i = 1; i < nextClassId; i++)
{
tracking[i].reset();
tracking[i].reset(tempClassIdStart);
}
currentClassId = fixedClassId;
nextClassId = tempClassIdStart;
}
public ClassInfo getClassInfo(Class clazz)
@ -48,7 +61,7 @@ public class ClassInfoResolver
ClassInfo classInfo = store.get(clazz);
if (classInfo == null)
{
classInfo = new ClassInfo().setClassName(clazz.getName()).setJfireSE(jfireSE).setClazz(clazz);
classInfo = new ClassInfo().setClassName(clazz.getName()).setJfireSE(jfireSE).setRefTracking(jfireSE.isRefTracking()).setClazz(clazz);
store.put(clazz, classInfo);
return classInfo;
}
@ -60,24 +73,29 @@ public class ClassInfoResolver
ClassInfo classInfo = getClassInfo(clazz);
if (classInfo == null)
{
classInfo = new ClassInfo().setClassName(clazz.getName()).setJfireSE(jfireSE).setClazz(clazz);
classInfo = new ClassInfo().setClassName(clazz.getName()).setJfireSE(jfireSE).setRefTracking(jfireSE.isRefTracking()).setClazz(clazz);
store.put(clazz, classInfo);
}
for (int i = 1; i < fixedClassId; i++)
for (int i = 1; i < tempClassIdStart; i++)
{
if (tracking[i].getClazz() == clazz)
{
return;
}
}
if (fixedClassId > tracking.length)
if (tempClassIdStart > tracking.length)
{
ClassInfo[] newTracking = new ClassInfo[tracking.length << 1];
System.arraycopy(tracking, 0, newTracking, 0, tracking.length);
tracking = newTracking;
}
tracking[fixedClassId] = classInfo;
classInfo.setClassId(fixedClassId++);
currentClassId = fixedClassId;
tracking[tempClassIdStart] = classInfo;
classInfo.setClassId(tempClassIdStart++);
nextClassId = tempClassIdStart;
}
public ClassInfo getClassInfo(int classId)
{
return tracking[classId];
}
}

View File

@ -2,19 +2,24 @@ package com.jfirer.se;
import com.jfirer.se.serializer.Serializer;
import com.jfirer.se.serializer.SerializerResolver;
import lombok.Getter;
import lombok.experimental.Accessors;
import java.util.HashMap;
import java.util.Map;
@Accessors(chain = true)
public class JfireSE
{
public static final byte NULL = 0;
private boolean CYCLE_SUPPORT = true;
private SerializerResolver serializerResolver;
private ClassInfoResolver classInfoResolver;
private int depth = 1;
public boolean isCycleSupport()
{
return CYCLE_SUPPORT;
}
public static final byte NULL = 0;
public static final byte NOT_NULL = 1;
@Getter
private boolean refTracking = true;
private SerializerResolver serializerResolver = new SerializerResolver();
private ClassInfoResolver classInfoResolver = new ClassInfoResolver(this);
private int depth = 1;
private Map<String, Class<?>> classNameMap = new HashMap<>();
private InternalByteArray byteArray = new InternalByteArray(1024);
public Serializer getSerializer(Class clazz)
{
@ -26,6 +31,23 @@ public class JfireSE
return classInfoResolver.getClassInfo(clazz);
}
public ClassInfo getClassInfo(String className)
{
Class<?> clazz = classNameMap.computeIfAbsent(className, name -> {
try
{
return Class.forName(name);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
});
ClassInfo classInfo = getClassInfo(clazz);
getClassId(classInfo);
return classInfo;
}
public void getClassId(ClassInfo classInfo)
{
classInfoResolver.getClassId(classInfo);
@ -43,4 +65,76 @@ public class JfireSE
{
depth--;
}
public byte[] writeBytes(Object instance)
{
if (instance == null)
{
byteArray.put(NULL);
}
else
{
ClassInfo classInfo = getClassInfo(instance.getClass());
classInfo.writeBytes(byteArray, instance, false);
classInfoResolver.reset();
}
byte[] result = byteArray.toArray();
byteArray.setWritePosi(0);
return result;
}
public Object readBytes(byte[] bytes)
{
return readBytes(new InternalByteArray(bytes));
}
public Object readBytes(InternalByteArray byteArray)
{
byte flag = byteArray.get();
switch (flag)
{
case 0 -> {return null;}
case 1 ->
{
String className = byteArray.readString();
ClassInfo classInfo = getClassInfo(className);
return classInfo.readBytes(byteArray, true);
}
case 2 ->
{
String className = byteArray.readString();
ClassInfo classInfo = getClassInfo(className);
return classInfo.readBytes(byteArray, false);
}
case 3, 7, 8, 9 ->
{
throw new IllegalArgumentException();
}
case 4 ->
{
int classId = byteArray.readVarInt();
ClassInfo classInfo = classInfoResolver.getClassInfo(classId);
return classInfo.readBytes(byteArray, true);
}
case 5 ->
{
int classId = byteArray.readVarInt();
ClassInfo classInfo = classInfoResolver.getClassInfo(classId);
return classInfo.readBytes(byteArray, false);
}
case 6 ->
{
int classId = byteArray.readVarInt();
int instanceId = byteArray.readVarInt();
ClassInfo classInfo = classInfoResolver.getClassInfo(classId);
return classInfo.getTracking(instanceId);
}
default -> throw new IllegalArgumentException();
}
}
public void registerClass(Class clazz)
{
classInfoResolver.registerClass(clazz);
}
}

View File

@ -5,4 +5,6 @@ import com.jfirer.se.InternalByteArray;
public interface Serializer
{
void writeBytes(InternalByteArray byteArray, Object instance);
Object readBytes(InternalByteArray byteArray);
}

View File

@ -1,13 +1,39 @@
package com.jfirer.se.serializer;
import com.jfirer.se.InternalByteArray;
import com.jfirer.se.JfireSE;
import com.jfirer.se.serializer.impl.ArraySerializer;
import com.jfirer.se.serializer.impl.ObjectSerializer;
import io.github.karlatemp.unsafeaccessor.Unsafe;
import java.util.IdentityHashMap;
import java.util.Map;
public class SerializerResolver
{
private Map<Class, Serializer> store = new IdentityHashMap<>();
private Map<Class, Serializer> store = new IdentityHashMap<>();
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
public SerializerResolver()
{
store.put(int[].class, new IntArraySerializer());
store.put(long[].class, new LongArraySerializer());
store.put(double[].class, new DoubleArraySerializer());
store.put(float[].class, new FloatArraySerializer());
store.put(short[].class, new ShortArraySerializer());
store.put(char[].class, new CharArraySerializer());
store.put(byte[].class, new ByteArraySerializer());
store.put(boolean[].class, new BooleanArraySerializer());
store.put(Integer[].class, new BoxedIntArraySerializer());
store.put(Long[].class, new BoxedLongArraySerializer());
store.put(Double[].class, new BoxedDoubleArraySerializer());
store.put(Float[].class, new BoxedFloatArraySerializer());
store.put(Short[].class, new BoxedShortArraySerializer());
store.put(Character[].class, new BoxedCharArraySerializer());
store.put(Byte[].class, new BoxedByteArraySerializer());
store.put(Boolean[].class, new BoxedBooleanArraySerializer());
store.put(String[].class, new StringArraySerializer());
}
public Serializer getSerializer(Class clazz, JfireSE jfireSE)
{
@ -16,10 +42,659 @@ public class SerializerResolver
{
return serializer;
}
if (clazz.isArray())
{
serializer = new ArraySerializer(clazz, jfireSE);
}
else
{
serializer = new ObjectSerializer(clazz, jfireSE);
}
store.put(clazz, serializer);
return serializer;
}
public void registerSerializer(Class clazz, Serializer serializer)
{
store.put(clazz, serializer);
}
private static int getShift(int value)
{
int count = 0;
while (value != 0)
{
count++;
value >>= 1;
}
return count-1;
}
class IntArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(int[].class);
int shift = getShift(UNSAFE.arrayIndexScale(int[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
int[] array = (int[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.writeVarInt(UNSAFE.getInt(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
int[] array = new int[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putInt(array, offset + ((long) i << shift), byteArray.readVarInt());
}
return array;
}
}
class LongArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(long[].class);
int shift = getShift(UNSAFE.arrayIndexScale(long[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
long[] array = (long[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.writeVarLong(UNSAFE.getLong(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
long[] array = new long[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putLong(array, offset + ((long) i << shift), byteArray.readVarLong());
}
return array;
}
}
class DoubleArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(double[].class);
int shift = getShift(UNSAFE.arrayIndexScale(double[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
double[] array = (double[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.writeDouble(UNSAFE.getDouble(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
double[] array = new double[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putDouble(array, offset + ((long) i << shift), byteArray.readDouble());
}
return array;
}
}
class FloatArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(float[].class);
int shift = getShift(UNSAFE.arrayIndexScale(float[].class) );
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
float[] array = (float[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.writeFloat(UNSAFE.getFloat(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
float[] array = new float[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putFloat(array, offset + ((long) i << shift), byteArray.readFloat());
}
return array;
}
}
class CharArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(char[].class);
int shift = getShift(UNSAFE.arrayIndexScale(char[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
char[] array = (char[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.writeVarChar(UNSAFE.getChar(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
char[] array = new char[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putChar(array, offset + ((long) i << shift), byteArray.readVarChar());
}
return array;
}
}
class ShortArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(short[].class);
int shift = getShift(UNSAFE.arrayIndexScale(short[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
short[] array = (short[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.writeShort(UNSAFE.getShort(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
short[] array = new short[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putShort(array, offset + ((long) i << shift), byteArray.readShort());
}
return array;
}
}
class ByteArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(byte[].class);
int shift = getShift(UNSAFE.arrayIndexScale(byte[].class) );
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
byte[] array = (byte[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.put(UNSAFE.getByte(array, offset + ((long) i << shift)));
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
byte[] array = new byte[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putByte(array, offset + ((long) i << shift), byteArray.get());
}
return array;
}
}
class BooleanArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(boolean[].class);
int shift = getShift(UNSAFE.arrayIndexScale(boolean[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
boolean[] array = (boolean[]) instance;
byteArray.writeVarInt(array.length);
for (int i = 0; i < array.length; i++)
{
byteArray.put(UNSAFE.getBoolean(array, offset + ((long) i << shift)) ? (byte) 1 : (byte) 0);
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
boolean[] array = new boolean[length];
for (int i = 0; i < length; i++)
{
UNSAFE.putBoolean(array, offset + ((long) i << shift), byteArray.get() == 1);
}
return array;
}
}
class BoxedIntArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Integer[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Integer[].class) );
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Integer[] array = (Integer[]) instance;
byteArray.writeVarInt(array.length);
for (Integer i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeVarInt(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Integer[] array = new Integer[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readVarInt());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedLongArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Long[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Long[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Long[] array = (Long[]) instance;
byteArray.writeVarInt(array.length);
for (Long i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeVarLong(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Long[] array = new Long[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readVarLong());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedDoubleArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Double[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Double[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Double[] array = (Double[]) instance;
byteArray.writeVarInt(array.length);
for (Double i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeDouble(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Double[] array = new Double[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readDouble());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedFloatArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Float[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Float[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Float[] array = (Float[]) instance;
byteArray.writeVarInt(array.length);
for (Float i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeFloat(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Float[] array = new Float[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readFloat());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedBooleanArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Boolean[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Boolean[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Boolean[] array = (Boolean[]) instance;
byteArray.writeVarInt(array.length);
for (Boolean i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.put(i ? (byte) 1 : 0);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Boolean[] array = new Boolean[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.get() == 1);
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedCharArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Character[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Character[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Character[] array = (Character[]) instance;
byteArray.writeVarInt(array.length);
for (Character i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeVarChar(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Character[] array = new Character[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readVarChar());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedByteArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Byte[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Byte[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Byte[] array = (Byte[]) instance;
byteArray.writeVarInt(array.length);
for (Byte i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.put(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Byte[] array = new Byte[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.get());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class BoxedShortArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(Short[].class);
int shift = getShift(UNSAFE.arrayIndexScale(Short[].class) );
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
Short[] array = (Short[]) instance;
byteArray.writeVarInt(array.length);
for (Short i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeShort(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Short[] array = new Short[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readShort());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
class StringArraySerializer implements Serializer
{
long offset = UNSAFE.arrayBaseOffset(String[].class);
int shift = getShift(UNSAFE.arrayIndexScale(String[].class));
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
String[] array = (String[]) instance;
byteArray.writeVarInt(array.length);
for (String i : array)
{
if (i == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeString(i);
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
String[] array = new String[length];
for (int i = 0; i < length; i++)
{
if (byteArray.get() == JfireSE.NOT_NULL)
{
UNSAFE.putReference(array, offset + ((long) i << shift), byteArray.readString());
}
else
{
UNSAFE.putReference(array, offset + ((long) i << shift), null);
}
}
return array;
}
}
}

View File

@ -0,0 +1,99 @@
package com.jfirer.se.serializer.impl;
import com.jfirer.se.ClassInfo;
import com.jfirer.se.InternalByteArray;
import com.jfirer.se.JfireSE;
import com.jfirer.se.serializer.Serializer;
import io.github.karlatemp.unsafeaccessor.Unsafe;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
@SuppressWarnings("rawtypes")
public class ArraySerializer implements Serializer
{
private Class componentType;
private int arrayBaseOffset;
private int arrayIndexScale;
private int arrayIndexScaleShift;
private boolean componentTypeFinal;
private ClassInfo classInfoOfComponentTypeFinal;
private ClassInfo cachedClassInfo;
private JfireSE jfireSE;
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
public ArraySerializer(Class clazz, JfireSE jfireSE)
{
this.jfireSE = jfireSE;
componentType = clazz.getComponentType();
arrayBaseOffset = UNSAFE.arrayBaseOffset(clazz);
arrayIndexScale = UNSAFE.arrayIndexScale(clazz);
arrayIndexScaleShift = arrayIndexScale == 4 ? 2 : 3;
componentTypeFinal = Modifier.isFinal(componentType.getModifiers());
if (componentTypeFinal)
{
classInfoOfComponentTypeFinal = jfireSE.getClassInfo(componentType);
}
}
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
int length = ((Object[]) instance).length;
byteArray.writeVarInt(length);
for (int i = 0; i < length; i++)
{
Object element = UNSAFE.getReference(instance, arrayBaseOffset + ((long) i << arrayIndexScaleShift));
if (element == null)
{
byteArray.put(JfireSE.NULL);
}
else
{
if (componentTypeFinal)
{
classInfoOfComponentTypeFinal.writeBytes(byteArray, element, true);
}
else
{
if (cachedClassInfo != null && cachedClassInfo.getClazz() == element.getClass())
{
cachedClassInfo.writeBytes(byteArray, element, false);
}
else
{
cachedClassInfo = jfireSE.getClassInfo(element.getClass());
cachedClassInfo.writeBytes(byteArray, element, false);
}
}
}
}
}
@Override
public Object readBytes(InternalByteArray byteArray)
{
int length = byteArray.readVarInt();
Object array = Array.newInstance(componentType, length);
for (int i = 0; i < length; i++)
{
if (componentTypeFinal)
{
int flag = byteArray.readVarInt();
switch (flag)
{
case JfireSE.NULL -> UNSAFE.putReference(array, arrayBaseOffset + ((long) i << arrayIndexScaleShift), null);
case 7 -> UNSAFE.putReference(array, arrayBaseOffset + ((long) i << arrayIndexScaleShift), classInfoOfComponentTypeFinal.readBytes(byteArray, true));
case 8 -> UNSAFE.putReference(array, arrayBaseOffset + ((long) i << arrayIndexScaleShift), classInfoOfComponentTypeFinal.readBytes(byteArray, false));
case 9 -> UNSAFE.putReference(array, arrayBaseOffset + ((long) i << arrayIndexScaleShift), classInfoOfComponentTypeFinal.getTracking(byteArray.readVarInt()));
default -> throw new IllegalArgumentException();
}
}
else
{
UNSAFE.putReference(array, arrayBaseOffset + ((long) i << arrayIndexScaleShift), jfireSE.readBytes(byteArray));
}
}
return array;
}
}

View File

@ -6,23 +6,25 @@ import com.jfirer.se.ClassInfo;
import com.jfirer.se.InternalByteArray;
import com.jfirer.se.JfireSE;
import com.jfirer.se.serializer.Serializer;
import io.github.karlatemp.unsafeaccessor.Unsafe;
import lombok.Data;
import lombok.SneakyThrows;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.*;
import java.util.function.Predicate;
@SuppressWarnings("rawtypes")
public class ObjectSerializer implements Serializer
{
private FieldInfo[] primitiveFieldInfos;
private FieldInfo[] boxFieldInfos;
private FinalFieldInfo[] finalFieldInfos;
private JfireSE jfireSE;
private Class clazz;
private FieldInfo[] primitiveFieldInfos;
private FieldInfo[] boxFieldInfos;
private FinalFieldInfo[] finalFieldInfos;
private VariableFieldInfo[] variableFieldInfos;
private JfireSE jfireSE;
private Class clazz;
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
public ObjectSerializer(Class clazz, JfireSE jfireSE)
{
@ -33,19 +35,69 @@ public class ObjectSerializer implements Serializer
while (type != Object.class)
{
fields.addAll(Arrays.stream(type.getDeclaredFields()).filter(Predicate.not(field -> Modifier.isStatic(field.getModifiers()))).toList());
type = type.getComponentType();
type = type.getSuperclass();
}
primitiveFieldInfos = fields.stream().filter(field -> field.getType().isPrimitive()).sorted(Comparator.comparing(o -> o.getType().getName())).map(FieldInfo::new).toArray(FieldInfo[]::new);
boxFieldInfos = fields.stream().filter(field -> ReflectUtil.isPrimitiveBox(field.getType()) || field.getType() == String.class).sorted(Comparator.comparing(o -> o.getType().getName())).map(FieldInfo::new).toArray(FieldInfo[]::new);
finalFieldInfos = fields.stream().filter(Predicate.not(field -> ReflectUtil.isPrimitiveBox(field.getType())))//
.filter(Predicate.not(field -> ReflectUtil.isPrimitive(field.getType())))//
.filter(field -> field.getType() != String.class)//
.filter(field -> field.getType() != void.class && field.getType() != Void.class)//
.filter(field -> Modifier.isFinal(field.getType().getModifiers())).sorted(Comparator.comparing(o -> o.getType().getName())).map(FinalFieldInfo::new).toArray(FinalFieldInfo[]::new);
.filter(field -> Modifier.isFinal(field.getType().getModifiers()))//
.sorted(Comparator.comparing(o -> o.getType().getName()))//
.map(FinalFieldInfo::new).toArray(FinalFieldInfo[]::new);
variableFieldInfos = fields.stream().filter(Predicate.not(field -> ReflectUtil.isPrimitiveBox(field.getType())))//
.filter(Predicate.not(field -> ReflectUtil.isPrimitive(field.getType())))//
.filter(field -> field.getType() != String.class)//
.filter(field -> field.getType() != void.class && field.getType() != Void.class)//
.filter(field -> !Modifier.isFinal(field.getType().getModifiers()))//
.sorted(Comparator.comparing(o -> o.getType().getName()))//
.map(VariableFieldInfo::new).toArray(VariableFieldInfo[]::new);
}
@Override
public void writeBytes(InternalByteArray byteArray, Object instance)
{
for (FieldInfo primitiveFieldInfo : primitiveFieldInfos)
{
primitiveFieldInfo.write(byteArray, instance);
}
for (FieldInfo boxFieldInfo : boxFieldInfos)
{
boxFieldInfo.write(byteArray, instance);
}
for (FinalFieldInfo finalFieldInfo : finalFieldInfos)
{
finalFieldInfo.write(byteArray, instance);
}
for (VariableFieldInfo variableFieldInfo : variableFieldInfos)
{
variableFieldInfo.write(byteArray, instance);
}
}
@SneakyThrows
@Override
public Object readBytes(InternalByteArray byteArray)
{
Object instance = UNSAFE.allocateInstance(clazz);
for (FieldInfo primitiveFieldInfo : primitiveFieldInfos)
{
primitiveFieldInfo.read(byteArray, instance);
}
for (FieldInfo boxFieldInfo : boxFieldInfos)
{
boxFieldInfo.read(byteArray, instance);
}
for (FinalFieldInfo finalFieldInfo : finalFieldInfos)
{
finalFieldInfo.read(byteArray, instance);
}
for (VariableFieldInfo variableFieldInfo : variableFieldInfos)
{
variableFieldInfo.read(byteArray, instance);
}
return instance;
}
@Data
@ -60,6 +112,120 @@ public class ObjectSerializer implements Serializer
accessor = new ValueAccessor(field);
}
void read(InternalByteArray byteArray, Object instance)
{
switch (classId)
{
case ReflectUtil.PRIMITIVE_INT -> accessor.set(instance, byteArray.readVarInt());
case ReflectUtil.PRIMITIVE_LONG -> accessor.set(instance, byteArray.readVarLong());
case ReflectUtil.PRIMITIVE_FLOAT -> accessor.set(instance, byteArray.readFloat());
case ReflectUtil.PRIMITIVE_DOUBLE -> accessor.set(instance, byteArray.readDouble());
case ReflectUtil.PRIMITIVE_BOOL -> accessor.set(instance, byteArray.readPositive() == 1);
case ReflectUtil.PRIMITIVE_CHAR -> accessor.set(instance, byteArray.readVarChar());
case ReflectUtil.PRIMITIVE_SHORT -> accessor.set(instance, byteArray.readShort());
case ReflectUtil.PRIMITIVE_BYTE -> accessor.set(instance, byteArray.get());
case ReflectUtil.CLASS_INT ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readVarInt());
}
}
case ReflectUtil.CLASS_LONG ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readVarLong());
}
}
case ReflectUtil.CLASS_FLOAT ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readFloat());
}
}
case ReflectUtil.CLASS_DOUBLE ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readDouble());
}
}
case ReflectUtil.CLASS_BOOL ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readPositive() == 1);
}
}
case ReflectUtil.CLASS_CHAR ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readVarChar());
}
}
case ReflectUtil.CLASS_SHORT ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.readShort());
}
}
case ReflectUtil.CLASS_BYTE ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.set(instance, byteArray.get());
}
}
case ReflectUtil.CLASS_STRING ->
{
if (byteArray.get() == JfireSE.NULL)
{
accessor.setObject(instance, null);
}
else
{
accessor.setObject(instance, byteArray.readString());
}
}
}
}
void write(InternalByteArray byteArray, Object instance)
{
switch (classId)
@ -81,7 +247,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeVarInt(value);
}
}
@ -94,7 +260,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeVarLong(value);
}
}
@ -107,7 +273,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeFloat(value);
}
}
@ -120,7 +286,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeDouble(value);
}
}
@ -133,7 +299,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writePositive(value ? 1 : 0);
}
}
@ -146,7 +312,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeVarChar(value);
}
}
@ -159,7 +325,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeShort(value);
}
}
@ -172,7 +338,7 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.put(value);
}
}
@ -185,10 +351,11 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 01);
byteArray.put(JfireSE.NOT_NULL);
byteArray.writeString(value);
}
}
default -> throw new IllegalArgumentException();
}
}
}
@ -213,8 +380,20 @@ public class ObjectSerializer implements Serializer
}
else
{
byteArray.put((byte) 07);
classInfo.writeBytes(byteArray, value, true);
}
}
public void read(InternalByteArray byteArray, Object instance)
{
byte flag = byteArray.get();
switch (flag)
{
case JfireSE.NULL -> accessor.setObject(instance, null);
case 7 -> accessor.setObject(instance, classInfo.readBytes(byteArray, true));
case 8 -> accessor.setObject(instance, classInfo.readBytes(byteArray, false));
case 9 -> accessor.setObject(instance, classInfo.getTracking(byteArray.readVarInt()));
default -> throw new IllegalArgumentException();
}
}
}
@ -228,5 +407,31 @@ public class ObjectSerializer implements Serializer
{
accessor = new ValueAccessor(field);
}
void write(InternalByteArray byteArray, Object instance)
{
if (instance == null)
{
byteArray.put(JfireSE.NULL);
return;
}
Class<?> clazz = instance.getClass();
if (classInfo != null && classInfo.getClazz() == clazz)
{
classInfo.writeBytes(byteArray, instance, false);
}
else
{
classInfo = jfireSE.getClassInfo(clazz);
classInfo.writeBytes(byteArray, instance, false);
}
}
void read(InternalByteArray byteArray, Object instance)
{
accessor.setObject(instance, jfireSE.readBytes(byteArray));
}
}
}

View File

@ -1,38 +0,0 @@
package org.example;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

View File

@ -0,0 +1,69 @@
package org.example;
import com.jfirer.fse.ByteArray;
import com.jfirer.fse.Fse;
import com.jfirer.se.JfireSE;
import io.fury.Fury;
import io.fury.config.Language;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 2, time = 1)
@Measurement(iterations = 3, time = 3)
@OutputTimeUnit(TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Benchmark)
public class BenchMark
{
Fse fse = new Fse();
Fse fse_3 = new Fse().useCompile();
TestData data = new TestData();
ByteArray buf = ByteArray.allocate(100);
Fury fury = Fury.builder().withLanguage(Language.JAVA)//
.requireClassRegistration(false)//
.withRefTracking(true).build();
JfireSE jfireSE = new JfireSE();
@Setup
public void before(){
jfireSE.registerClass(TestData.class);
}
@Benchmark
public void testNoCompile()
{
buf.clear();
fse.serialize(data, buf);
}
@Benchmark
public void testFury()
{
byte[] bytes = fury.serialize(data);
}
@Benchmark
public void testDirectCompile()
{
buf.clear();
fse_3.serialize(data, buf);
}
@Benchmark
public void testJfireSE()
{
jfireSE.writeBytes(data);
}
public static void main(String[] args) throws RunnerException
{
Options opt = new OptionsBuilder().include(BenchMark.class.getSimpleName()).build();
new Runner(opt).run();
}
}

View File

@ -0,0 +1,30 @@
package org.example;
import com.jfirer.se.JfireSE;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class FunctionTest
{
@Test
public void test()
{
JfireSE jfireSE = new JfireSE();
TestData data = new TestData();
//创建一个二进制数组容器,用于容纳序列化后的输出。容器大小会在需要时自动扩大,入参仅决定初始化大小。
//执行序列化,会将序列化对象序列化到二进制数组容器之中。
byte[] bytes = jfireSE.writeBytes(data);
TestData result = (TestData) jfireSE.readBytes(bytes);
assertTrue(result.equals(data));
}
@Test
public void test2()
{
TestData data = new TestData();
JfireSE jfireSE = new JfireSE();
byte[] bytes = jfireSE.writeBytes(data);
Object o = jfireSE.readBytes(bytes);
}
}

View File

@ -0,0 +1,110 @@
package org.example;
import java.io.Serializable;
public class TestData implements Serializable
{
private int a = 213212312;
private boolean b = false;
private char c = 'c';
private byte d = 0x11;
private short e = 24;
private long f = 1213124131312321L;
private double g = 231321.2132;
private float h = (float) 4986.2;
// private String i = "123452312316789a";
// private int[] j = new int[]{1, 2, 4, 5};
// private boolean[] k = new boolean[]{true, false, true, false, false, false, true};
// private char[] l = new char[]{'a', 'v', 'q', 'j', 'h', 'e', 'f'};
// private byte[] m = new byte[]{0x32, 0x12, 0x34, (byte) 0x96};
// private short[] n = new short[]{3, 8, 213, 451, 312, 45};
// private long[] o = new long[]{12313131313l, 524141431313l, 3131231231425l, 1313123121l};
// private double[] p = new double[]{6468613646.48646d, 4646.456d, 546864648867.466d};
// private float[] q = new float[]{46486.2f, 49849.2f, 646854.6f};
// private String[] r = new String[]{"abcdf12345", "abdfcgf12323"};
public boolean equals(Object x)
{
if (x instanceof TestData)
{
TestData target = (TestData) x;
// if (target.a == a && target.b == b && target.c == c && target.d == d && target.e == e && target.f == f && target.g == g && target.h == h && target.i.equals(i))
// {
// for (int i = 0; i < target.j.length; i++)
// {
// if (target.j[i] != j[i])
// {
// return false;
// }
// }
// for (int i = 0; i < k.length; i++)
// {
// if (target.k[i] != k[i])
// {
// return false;
// }
// }
// for (int i = 0; i < l.length; i++)
// {
// if (target.l[i] != l[i])
// {
// return false;
// }
// }
// for (int i = 0; i < m.length; i++)
// {
// if (target.m[i] != m[i])
// {
// return false;
// }
// }
// for (int i = 0; i < n.length; i++)
// {
// if (target.n[i] != n[i])
// {
// return false;
// }
// }
// for (int i = 0; i < o.length; i++)
// {
// if (target.o[i] != o[i])
// {
// return false;
// }
// }
// for (int i = 0; i < p.length; i++)
// {
// if (p[i] != target.p[i])
// {
// return false;
// }
// }
// for (int i = 0; i < r.length; i++)
// {
// if (target.r[i].equals(r[i]) == false)
// {
// return false;
// }
// }
// for (int i = 0; i < q.length; i++)
// {
// if (q[i] != target.q[i])
// {
// return false;
// }
// }
// return true;
// }
// else
// {
// return false;
// }
}
else
{
return false;
}
return false;
}
}