Skip to content

Commit 3a6ab86

Browse files
author
zhourenjian@gmail.com
committed
Adjust the serialize/deserialize field type order, set integer and String fields first
Optimize SimpleSerializable performance Add options to avoid calculating differences on SimpleRPCRunnable before and after ajaxRun Add options to avoid GZip encoding
1 parent f4bbea3 commit 3a6ab86

4 files changed

Lines changed: 808 additions & 775 deletions

File tree

sources/net.sf.j2s.ajax/ajaxrpc/net/sf/j2s/ajax/SimpleRPCHttpServlet.java

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@ public class SimpleRPCHttpServlet extends HttpServlet {
5252

5353
protected boolean managingPipe = false;
5454

55+
private static SimpleFilter NO_DELTA_FILTER = new SimpleFilter() {
56+
57+
public boolean accept(String field) {
58+
return true;
59+
}
60+
61+
public boolean ignoreDefaultFields() {
62+
return false;
63+
}
64+
65+
};
66+
5567
protected long maxPostLimit() {
5668
return postLimit;
5769
}
@@ -261,23 +273,24 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
261273
//e.printStackTrace();
262274
}
263275
runnable.ajaxRun();
264-
final String[] diffs = SimpleRPCUtils.compareDiffs(runnable, clonedRunnable);
265-
String serialize = runnable.serialize(new SimpleFilter() {
266-
267-
public boolean accept(String field) {
268-
for (int i = 0; i < diffs.length; i++) {
269-
if (diffs[i].equals(field)) {
270-
return true;
271-
}
276+
SimpleFilter filter = null;
277+
if (runnable.supportsDeltaResponse()) {
278+
final Set<String> diffs = SimpleRPCUtils.compareDiffs(runnable, clonedRunnable);
279+
filter = new SimpleFilter() {
280+
281+
public boolean accept(String field) {
282+
return diffs.contains(field);
272283
}
273-
return false;
274-
}
275-
276-
public boolean ignoreDefaultFields() {
277-
return false;
278-
}
279-
280-
});
284+
285+
public boolean ignoreDefaultFields() {
286+
return false;
287+
}
288+
289+
};
290+
} else { // all fields are returned.
291+
filter = NO_DELTA_FILTER;
292+
}
293+
String serialize = runnable.serialize(filter);
281294

282295
writer.write(serialize);
283296
runnable.ajaxOut();
@@ -324,29 +337,32 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
324337
return;
325338
}
326339
SimpleRPCRunnable clonedRunnable = null;
327-
try {
328-
clonedRunnable = (SimpleRPCRunnable) runnable.clone();
329-
} catch (CloneNotSupportedException e) {
330-
//e.printStackTrace();
340+
if (runnable.supportsDeltaResponse()) {
341+
try {
342+
clonedRunnable = (SimpleRPCRunnable) runnable.clone();
343+
} catch (CloneNotSupportedException e) {
344+
//e.printStackTrace();
345+
}
331346
}
332347
runnable.ajaxRun();
333-
final String[] diffs = SimpleRPCUtils.compareDiffs(runnable, clonedRunnable);
334-
String serialize = runnable.serialize(new SimpleFilter() {
335-
336-
public boolean accept(String field) {
337-
for (int i = 0; i < diffs.length; i++) {
338-
if (diffs[i].equals(field)) {
339-
return true;
340-
}
348+
SimpleFilter filter = null;
349+
if (runnable.supportsDeltaResponse()) {
350+
final Set<String> diffs = SimpleRPCUtils.compareDiffs(runnable, clonedRunnable);
351+
filter = new SimpleFilter() {
352+
353+
public boolean accept(String field) {
354+
return diffs.contains(field);
341355
}
342-
return false;
343-
}
344-
345-
public boolean ignoreDefaultFields() {
346-
return false;
347-
}
348-
349-
});
356+
357+
public boolean ignoreDefaultFields() {
358+
return false;
359+
}
360+
361+
};
362+
} else { // all fields are returned.
363+
filter = NO_DELTA_FILTER;
364+
}
365+
String serialize = runnable.serialize(filter);
350366

351367
resp.setHeader("Pragma", "no-cache");
352368
resp.setHeader("Cache-Control", "no-cache");

sources/net.sf.j2s.ajax/ajaxrpc/net/sf/j2s/ajax/SimpleRPCRunnable.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
package net.sf.j2s.ajax;
1313

14-
1514
/**
1615
* @author zhou renjian
1716
*
@@ -48,5 +47,32 @@ public String getHttpMethod() {
4847
* Called by local Java thread of XMLHttpRequest when #ajaxRun contains errors
4948
*/
5049
public void ajaxFail() {};
50+
51+
/**
52+
* Whether serializing delta updates in response only or not. Supporting
53+
* delta updates will save connection bandwidth but increase the CPU usage.
54+
*
55+
* This method will be called by server side.
56+
*
57+
* @return supported
58+
*/
59+
public boolean supportsDeltaResponse() {
60+
return true;
61+
}
62+
63+
/**
64+
* Whether sending out response in GZip encoding or not. Supporting GZip
65+
* encoding will save connection bandwidth but increase the CPU usage.
66+
*
67+
* For those RPC with already-encoded bytes, for example, PNG/JPEG images,
68+
* AAC/MP3 audio, H.265 movies and others, GZip encoding should be closed.
69+
*
70+
* This method will be called by server side.
71+
*
72+
* @return supported
73+
*/
74+
public boolean supportsGZipEncoding() {
75+
return true;
76+
}
5177

5278
}
Lines changed: 86 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package net.sf.j2s.ajax;
22

33
import java.lang.reflect.Field;
4-
import java.lang.reflect.Modifier;
54
import java.util.Arrays;
65
import java.util.HashSet;
6+
import java.util.Iterator;
7+
import java.util.Map;
78
import java.util.Set;
89

910
public class SimpleRPCUtils {
@@ -15,117 +16,110 @@ public class SimpleRPCUtils {
1516
*
1617
* @param runnable1 original object
1718
* @param runnable2 modified object
18-
* @return Names of the modified fields.
19+
* @return Name set of the modified fields.
1920
*
2021
* @j2sIgnore
2122
*/
22-
public static String[] compareDiffs(SimpleRPCRunnable runnable1, SimpleRPCRunnable runnable2) {
23+
public static Set<String> compareDiffs(SimpleRPCRunnable runnable1, SimpleRPCRunnable runnable2) {
2324
Set<String> diffSet = new HashSet<String>();
24-
Set<Field> fieldSet = new HashSet<Field>();
25-
Class<?> clazz = runnable1.getClass();
26-
while(clazz != null && !"net.sf.j2s.ajax.SimpleSerializable".equals(clazz.getName())) {
27-
Field[] fields = clazz.getDeclaredFields();
28-
for (int i = 0; i < fields.length; i++) {
29-
fieldSet.add(fields[i]);
30-
}
31-
clazz = clazz.getSuperclass();
32-
}
3325
String[] ignoredFields = runnable1.fieldDiffIgnored();
34-
Field[] fields = fieldSet.toArray(new Field[fieldSet.size()]);
35-
for (int i = 0; i < fields.length; i++) {
36-
Field field = fields[i];
37-
int modifiers = field.getModifiers();
38-
if ((modifiers & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0
39-
&& (modifiers & Modifier.TRANSIENT) == 0
40-
&& (modifiers & Modifier.STATIC) == 0) {
41-
String name = field.getName();
42-
if (ignoredFields != null) {
43-
boolean ignored = false;
44-
for (int j = 0; j < ignoredFields.length; j++) {
45-
if (name.equals(ignoredFields[j])) {
46-
ignored = true;
47-
break;
48-
}
49-
}
50-
if (ignored) {
51-
continue;
26+
Map<String, Field> allFields = runnable1.getSerializableFields(runnable1.getClass().getName());
27+
for (Iterator<String> itr = allFields.keySet().iterator(); itr.hasNext();) {
28+
String name = (String) itr.next();
29+
Field field = allFields.get(name);
30+
if (ignoredFields != null) {
31+
boolean ignored = false;
32+
for (int j = 0; j < ignoredFields.length; j++) {
33+
if (name.equals(ignoredFields[j])) {
34+
ignored = true;
35+
break;
5236
}
5337
}
54-
Object field1 = null;
55-
try {
56-
field1 = field.get(runnable1);
57-
} catch (IllegalArgumentException e1) {
58-
//e1.printStackTrace();
59-
} catch (IllegalAccessException e1) {
60-
//e1.printStackTrace();
38+
if (ignored) {
39+
continue;
6140
}
62-
Object field2 = null;
63-
try {
64-
field2 = field.get(runnable2);
65-
} catch (IllegalArgumentException e) {
66-
//e.printStackTrace();
67-
} catch (IllegalAccessException e) {
68-
//e.printStackTrace();
41+
}
42+
Object field1 = null;
43+
try {
44+
field1 = field.get(runnable1);
45+
} catch (IllegalArgumentException e1) {
46+
//e1.printStackTrace();
47+
} catch (IllegalAccessException e1) {
48+
//e1.printStackTrace();
49+
}
50+
Object field2 = null;
51+
try {
52+
field2 = field.get(runnable2);
53+
} catch (IllegalArgumentException e) {
54+
//e.printStackTrace();
55+
} catch (IllegalAccessException e) {
56+
//e.printStackTrace();
57+
}
58+
if (field1 == null) {
59+
if (field2 != null) {
60+
diffSet.add(name);
6961
}
70-
if (field1 == null) {
71-
if (field2 != null) {
62+
} else if (field2 == null) { // field1 != null
63+
diffSet.add(name);
64+
} else if (field.getType().isArray()) {
65+
Class<?> type = field.getType();
66+
if (type == int[].class) {
67+
if (!Arrays.equals((int[]) field1, (int[]) field2)) {
7268
diffSet.add(name);
7369
}
74-
} else if (field2 == null) { // field1 != null
70+
} else if (type == byte[].class) {
71+
if (!Arrays.equals((byte[]) field1, (byte[]) field2)) {
72+
diffSet.add(name);
73+
}
74+
} else if (type == String[].class) {
75+
if (!Arrays.equals((String[]) field1, (String[]) field2)) {
76+
diffSet.add(name);
77+
}
78+
} else if (SimpleSerializable.isSubclassOf(type, SimpleSerializable[].class)) {
7579
diffSet.add(name);
76-
} else if (field1.getClass().isArray()) {
77-
Class<?> type = field.getType();
78-
if (type == float[].class) {
79-
if (!Arrays.equals((float[]) field1, (float[]) field2)) {
80-
diffSet.add(name);
81-
}
82-
} else if (type == double[].class) {
83-
if (!Arrays.equals((double[]) field1, (double[]) field2)) {
84-
diffSet.add(name);
85-
}
86-
} else if (type == int[].class) {
87-
if (!Arrays.equals((int[]) field1, (int[]) field2)) {
88-
diffSet.add(name);
89-
}
90-
} else if (type == long[].class) {
91-
if (!Arrays.equals((long[]) field1, (long[]) field2)) {
92-
diffSet.add(name);
93-
}
94-
} else if (type == short[].class) {
95-
if (!Arrays.equals((short[]) field1, (short[]) field2)) {
96-
diffSet.add(name);
97-
}
98-
} else if (type == byte[].class) {
99-
if (!Arrays.equals((byte[]) field1, (byte[]) field2)) {
100-
diffSet.add(name);
101-
}
102-
} else if (type == char[].class) {
103-
if (!Arrays.equals((char[]) field1, (char[]) field2)) {
104-
diffSet.add(name);
105-
}
106-
} else if (type == boolean[].class) {
107-
if (!Arrays.equals((boolean[]) field1, (boolean[]) field2)) {
108-
diffSet.add(name);
109-
}
110-
} else if (type == String[].class) {
111-
if (!Arrays.equals((String[]) field1, (String[]) field2)) {
112-
diffSet.add(name);
113-
}
114-
} else if (SimpleSerializable.isSubclassOf(type, SimpleSerializable[].class)) {
80+
} else if (type == Object[].class) {
81+
if (!Arrays.equals((Object[]) field1, (Object[]) field2)) {
82+
diffSet.add(name);
83+
}
84+
} else if (type == long[].class) {
85+
if (!Arrays.equals((long[]) field1, (long[]) field2)) {
86+
diffSet.add(name);
87+
}
88+
} else if (type == boolean[].class) {
89+
if (!Arrays.equals((boolean[]) field1, (boolean[]) field2)) {
90+
diffSet.add(name);
91+
}
92+
} else if (type == float[].class) {
93+
if (!Arrays.equals((float[]) field1, (float[]) field2)) {
94+
diffSet.add(name);
95+
}
96+
} else if (type == double[].class) {
97+
if (!Arrays.equals((double[]) field1, (double[]) field2)) {
98+
diffSet.add(name);
99+
}
100+
} else if (type == short[].class) {
101+
if (!Arrays.equals((short[]) field1, (short[]) field2)) {
102+
diffSet.add(name);
103+
}
104+
} else if (type == char[].class) {
105+
if (!Arrays.equals((char[]) field1, (char[]) field2)) {
106+
diffSet.add(name);
107+
}
108+
}
109+
} else {
110+
Class<?> type = field.getType();
111+
if (type.isPrimitive() || type == String.class) {
112+
if (!field1.equals(field2)) {
115113
diffSet.add(name);
116-
} else if (type == Object[].class) {
117-
if (!Arrays.equals((Object[]) field1, (Object[]) field2)) {
118-
diffSet.add(name);
119-
}
120114
}
121-
} else if (SimpleSerializable.isSubclassOf(field.getType(), SimpleSerializable.class)) {
115+
} else if (SimpleSerializable.isSubclassOf(type, SimpleSerializable.class)) {
122116
diffSet.add(name);
123117
} else if (!field1.equals(field2)) {
124118
diffSet.add(name);
125119
}
126120
}
127121
}
128-
return diffSet.toArray(new String[diffSet.size()]);
122+
return diffSet;
129123
}
130124

131125
}

0 commit comments

Comments
 (0)