Skip to content

Commit

Permalink
speed test codegen speed by avoid duplicate codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
chaokunyang committed Oct 3, 2023
1 parent 129da75 commit 909ce89
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import org.testng.Assert;
Expand Down Expand Up @@ -123,7 +124,13 @@ public static Class<?> createCompatibleClass3() {
return loadClass(MapFields.class, code);
}

private static final ConcurrentHashMap<String, Class<?>> classCache = new ConcurrentHashMap<>();

static Class<?> loadClass(Class<?> cls, String code) {
return classCache.computeIfAbsent(code, k -> compileClass(cls, code));
}

private static Class<?> compileClass(Class<?> cls, String code) {
String pkg = ReflectionUtils.getPackage(cls);
Path path = Paths.get(pkg.replace(".", "/") + "/" + cls.getSimpleName() + ".java");
try {
Expand Down
157 changes: 86 additions & 71 deletions java/fury-test-core/src/main/java/io/fury/test/bean/Struct.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.tools.JavaCompiler;
Expand Down Expand Up @@ -182,92 +183,106 @@ public static Object createPOJO(Class<?> clz) {
}
}

private static final ConcurrentHashMap<Object, Class<?>> classCache = new ConcurrentHashMap<>();

/** Create class. */
public static Class<?> createNumberStructClass(String classname, int repeat) {
if (StringUtils.isBlank(classname)) {
classname = String.format("Struct%d", System.currentTimeMillis());
throw new IllegalArgumentException("Class name is empty");
}
StringBuilder classCode =
new StringBuilder(
String.format(
""
+ "import java.util.*;\n"
+ "public final class %s implements java.io.Serializable {\n"
+ " public String toString() {\n"
+ " return io.fury.test.bean.Struct.toString(this);\n"
+ " }\n"
+ " public boolean equals(Object o) {\n"
+ " return io.fury.test.bean.Struct.equalsWith(this, o);\n"
+ " }\n",
classname));
String key = "createNumberStructClass" + classname + repeat;
return classCache.computeIfAbsent(
key,
k -> {
StringBuilder classCode =
new StringBuilder(
String.format(
""
+ "import java.util.*;\n"
+ "public final class %s implements java.io.Serializable {\n"
+ " public String toString() {\n"
+ " return io.fury.test.bean.Struct.toString(this);\n"
+ " }\n"
+ " public boolean equals(Object o) {\n"
+ " return io.fury.test.bean.Struct.equalsWith(this, o);\n"
+ " }\n",
classname));

String fields =
""
+ " public boolean f%s;\n"
+ " public byte f%s;\n"
+ " public short f%s;\n"
+ " public int f%s;\n"
+ " public int f%s;\n"
+ " public long f%s;\n"
+ " public long f%s;\n"
+ " public float f%s;\n"
+ " public double f%s;\n"
+ " public Integer f%s;\n";
int numFields = 10;
for (int i = 0; i < repeat; i++) {
classCode.append(
String.format(
fields, IntStream.range(i * numFields, i * numFields + numFields).boxed().toArray()));
}
classCode.append("}");
return createStructClass(classname, classCode.toString());
String fields =
""
+ " public boolean f%s;\n"
+ " public byte f%s;\n"
+ " public short f%s;\n"
+ " public int f%s;\n"
+ " public int f%s;\n"
+ " public long f%s;\n"
+ " public long f%s;\n"
+ " public float f%s;\n"
+ " public double f%s;\n"
+ " public Integer f%s;\n";
int numFields = 10;
for (int i = 0; i < repeat; i++) {
classCode.append(
String.format(
fields,
IntStream.range(i * numFields, i * numFields + numFields).boxed().toArray()));
}
classCode.append("}");
return createStructClass(classname, classCode.toString());
});
}

/** Create Class. */
public static Class<?> createStructClass(String classname, int repeat) {
if (StringUtils.isBlank(classname)) {
classname = String.format("Struct%d", System.currentTimeMillis());
throw new IllegalArgumentException("Class name is empty");
}
StringBuilder classCode =
new StringBuilder(
String.format(
""
+ "import java.util.*;\n"
+ "public final class %s implements java.io.Serializable {\n"
+ " public String toString() {\n"
+ " return io.fury.test.bean.Struct.toString(this);\n"
+ " }\n"
+ " public boolean equals(Object o) {\n"
+ " return io.fury.test.bean.Struct.equalsWith(this, o);\n"
+ " }\n",
classname));
String key = "createStructClass" + classname + repeat;
return classCache.computeIfAbsent(
key,
k -> {
StringBuilder classCode =
new StringBuilder(
String.format(
""
+ "import java.util.*;\n"
+ "public final class %s implements java.io.Serializable {\n"
+ " public String toString() {\n"
+ " return io.fury.test.bean.Struct.toString(this);\n"
+ " }\n"
+ " public boolean equals(Object o) {\n"
+ " return io.fury.test.bean.Struct.equalsWith(this, o);\n"
+ " }\n",
classname));

String fields =
""
+ " public byte f%s;\n"
+ " public int f%s;\n"
+ " public long f%s;\n"
+ " public Integer f%s;\n"
+ " public String f%s;\n"
+ " public int[] f%s;\n"
+ " public Double[] f%s;\n"
+ " public List<Integer> list_int%s;\n"
+ " public List<String> list_str%s;\n"
+ " public Map<String, String> map_ss%s;\n"
+ " public Map<Long, Double> map_ld%s;\n"
+ " public Object obj%s;\n";
int numFields = 13;
for (int i = 0; i < repeat; i++) {
classCode.append(
String.format(
fields, IntStream.range(i * numFields, i * numFields + numFields).boxed().toArray()));
}
classCode.append("}");
return createStructClass(classname, classCode.toString());
String fields =
""
+ " public byte f%s;\n"
+ " public int f%s;\n"
+ " public long f%s;\n"
+ " public Integer f%s;\n"
+ " public String f%s;\n"
+ " public int[] f%s;\n"
+ " public Double[] f%s;\n"
+ " public List<Integer> list_int%s;\n"
+ " public List<String> list_str%s;\n"
+ " public Map<String, String> map_ss%s;\n"
+ " public Map<Long, Double> map_ld%s;\n"
+ " public Object obj%s;\n";
int numFields = 13;
for (int i = 0; i < repeat; i++) {
classCode.append(
String.format(
fields,
IntStream.range(i * numFields, i * numFields + numFields).boxed().toArray()));
}
classCode.append("}");
return createStructClass(classname, classCode.toString());
});
}

/** Create class. */
public static Class<?> createStructClass(String classname, String classCode) {
private static Class<?> createStructClass(String classname, String classCode) {

Path path = Paths.get(classname + ".java");
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class StructTest {

@Test
public void testStruct() {
Class<?> structClass = Struct.createStructClass("", 1);
Class<?> structClass = Struct.createStructClass("StructTestClass", 1);
Assert.assertEquals(Struct.createPOJO(structClass), Struct.createPOJO(structClass));
}
}

0 comments on commit 909ce89

Please sign in to comment.