2012-05-21 26 views
10

Ich versuche ein Array von 7000 POJO mit GSON zu serialisieren und die Serialisierungszeit ist extrem langsam. Es ist in der Größenordnung von 3-5 Sekunden eine Reihe von folgendem Objekt serialisiert werden:GSON Serialisierung sehr sehr langsam

public class Case { 
    private Long caseId; 
    private Key<Organization> orgKey; 

    private Key<Workflow> workflowKey; 
    private Key<User> creatorKey; 

    private Date creationTimestamp; 
    private Date lastUpdatedTimestamp; 

    private String name; 
    private String stage; 
    private String notes; 
} 

Die Schlüsselfelder serialisiert werden mit einem benutzerdefinierten Serializer/Deserializer:

public class GsonKeySerializerDeserializer implements JsonSerializer<Key<?>>, JsonDeserializer<Key<?>>{ 

@Override 
public JsonElement serialize(Key<?> src, Type typeOfSrc, JsonSerializationContext arg2) { 
    return new JsonPrimitive(src.getString()); 
} 

@Override 
public Key<?> deserialize(JsonElement src, Type typeOfSrc, JsonDeserializationContext arg2) throws JsonParseException { 
    if (src.isJsonNull() || src.getAsString().isEmpty()) { 
     return null; 
    } 

    String s = src.getAsString(); 
    com.google.appengine.api.datastore.Key k = KeyFactory.stringToKey(s); 
    return new Key(k); 
} 
} 

die Leistung gegen die Hand zu testen Beim Schreiben eines JSON-Serialisierers habe ich den folgenden Code getestet und könnte das gleiche Array von Case-Objekten ca. 10x schneller als GSON serialisieren.

List<Case> cases = (List<Case>) retVal; 
JSONArray a = new JSONArray(); 
for (Case c : cases) { 
    JSONObject o = new JSONObject(); 
    o.put("caseId", c.getCaseId()); 
    o.put("orgKey", c.getOrgKey().getString()); 
    o.put("workflowKey", c.getWorkflowKey().getString()); 
    o.put("creatorKey", c.getCreatorKey().getString()); 
    o.put("creationTimestamp", c.getCreationTimestamp().getTime()); 
    o.put("lastUpdatedTimestamp", c.getLastUpdatedTimestamp().getTime()); 
    o.put("name", c.getName()); 
    o.put("stage", c.getStage()); 
    o.put("notes", c.getNotes()); 
    a.put(o); 

} 
String json = a.toString(); 

Irgendwelche Ideen, warum GSON in diesem Fall so schlecht funktioniert?

UPDATE

Hier ist der Code, der tatsächlich die Serialisierung beginnt:

Object retVal = someFunctionThatReturnsAList(); 
String json = g.toJson(retVal); 
resp.getWriter().print(json); 

UPDATE2

Hier ist eine sehr einfache Testfall, der die schlechte Leistung in Bezug auf org.json zeigt :

List<Foo> list = new ArrayList<Foo>(); 
for (int i = 0; i < 7001; i++) { 
    Foo f = new Foo(); 
    f.id = new Long(i); 
    list.add(f); 
} 

Gson gs = new Gson(); 
long start = System.currentTimeMillis(); 
String s = gs.toJson(list); 
System.out.println("Serialization time using Gson: " + ((double) (System.currentTimeMillis() - start)/1000)); 


start = System.currentTimeMillis(); 
JSONArray a = new JSONArray(); 
for (Foo f : list) { 
    JSONObject o = new JSONObject(); 
    o.put("id", f.id); 
    a.put(o); 

} 
String json = a.toString(); 
System.out.println("Serialization time using org.json: " + ((double) (System.currentTimeMillis() - start)/1000)); 

System.out.println(json.equals(s)); 

Wo Foo ist:

public class Foo { 
public Long id; 
} 

Diese Ausgänge:

Serialization time using Gson: 0.233 
Serialization time using org.json: 0.028 
true 

Eine fast 10-fach Unterschied in der Leistung!

+0

Welche Version Gson verwenden Sie und was Ihr Code die Ausgabe zu erzeugen? – Joey

+0

Ich benutze Gson 2.2 und aktualisiere die Frage mit Code, um Ausgabe – aloo

+0

zu erzeugen Wie erstellst du dein Gson-Objekt? –

Antwort

4

Ich habe versucht, Ihr Problem zu reproduzieren und konnte nicht. Ich habe 7000 Objekte mit nichttrivialen Daten erstellt. Auf meinem ThinkPad dauerte es ~ 260 ms Gson, ~ 3 MB Gson zu serialisieren, was respektable ~ 10 Mbps ist.

Ein großer Teil dieser Zeit wurde für die Konvertierung von Daten in Zeichenfolgen verwendet. Das Konvertieren der zwei Datumsfelder in "Long" wurde ca. 50 ms gespeichert.

Ich konnte weitere ~ 10ms speichern, indem ich von Tree-Adaptern (JsonSerializer/JsonDeserializer) in die neue Streaming-Adapter-Klasse TypeAdaper migrierte. Der Code, der dies einrichtet sieht wie folgt aus:

private static TypeAdapter<Key<String>> keyAdapter = new TypeAdapter<Key<String>>() { 
     @Override public void write(JsonWriter out, Key<String> value) throws IOException { 
      out.value(value.value); 
     } 

     @Override public Key<String> read(JsonReader in) throws IOException { 
      if (in.peek() == JsonToken.NULL) { 
       in.nextNull(); 
       return null; 
      } 
      return new Key<String>(in.nextString()); 
     } 
    }; 

    ... 

    Gson gson = new GsonBuilder() 
      .registerTypeAdapter(Key.class, keyAdapter) 
      .create(); 

Der wesentliche Unterschied zwischen meinem Szenario und dein ist, dass ich meine eigene gefälschte Key-Klasse bin mit. Aber wenn der Schlüssel der Engpass wäre, der hätte entstehen sollen, wenn Sie jeden Fall manuell serialisiert haben.

Zur Behebung des Problems

Ihr bester nächster Schritt ist, Felder von Case zu entfernen, bis der Serialisierung verbessert. Es ist möglich, dass eines Ihrer Felder etwas enthält, das lange zu serialisieren braucht: vielleicht eine sehr lange Zeichenfolge, die übermäßiges Entkommen erfordert? Sobald Sie das Problem report a bug zu dem Gson-Projekt isolieren, werden wir das Problem gerne beheben.Zusätzlich zu dem Code, der das Problem reproduziert, sollten Sie auch Vertreter Daten enthalten.

+0

Wenn es übermäßige Flucht ist würde das Problem nicht auch in der manuellen Serialisierung auftauchen? – aloo

+0

Versuchen Sie Ihre anderen Strategien jetzt – aloo

+0

Ok Ich versuchte die TypeAdapter-Strategie und es scheint nicht viel zu helfen. Interessant ist, dass die Version meines Codes, der "von Hand" serialisiert, nicht nur die gleichen Felder (Schlüssel, Daten usw.) serialisiert, sondern dieselbe Methode wie die TypeAdapters verwendet, aber sie läuft buchstäblich 20x schneller. Dies scheint etwas falsch mit der Gson-Bibliothek selbst zu sein. – aloo