2012-11-01 18 views
7

in this thread ile ilgili yanlış eşleme sorunumu çözmek için özel Deserializers oluşturdum ve bunları ObjectMapper'a ekledim. Bununla birlikte, performans önemli ölçüde bozulur.Özel deserializer ile çıkarılan Jackson, çok fazla GC çağrısına neden oluyor ve çok daha uzun sürüyor

Varsayılan desperizatör ile 1-2 Çöp toplama çağrılarını logcat'dan alırken, özel desperizatörde en az 7-8 GC çağrısı olur ve bu nedenle işlem süresi de önemli ölçüde artar.

Benim Deserializer:

public class Deserializer<T> { 

public JsonDeserializer<T> getDeserializer(final Class<T> cls) { 
    return new JsonDeserializer<T>(){ 

    @Override 
    public T deserialize(JsonParser jp, DeserializationContext arg1) throws IOException, JsonProcessingException { 
     JsonNode node = jp.readValueAsTree(); 
     if (node.isObject()) { 
      return new ObjectMapper().convertValue(node, cls); 
     } 
     return null; 
    } 
}; 
} 
} 

Ve

public class DeserializerAttachedMapper<T> { 

    public ObjectMapper getMapperAttachedWith(final Class<T> cls , JsonDeserializer<T> deserializer) { 
     ObjectMapper mapper = new ObjectMapper(); 
     SimpleModule module = new SimpleModule(deserializer.toString(), new Version(1, 0, 0, null, null, null)); 
     module.addDeserializer(cls, deserializer); 
     mapper.registerModule(module); 
     return mapper; 
    } 
} 

DÜZENLEME Eşleştiricisi ekleme yapmak için bu kullanıyorum: Eklenen ek verileri

Benim JSON hatırı sayılır büyüklükte ama çok büyük değil taşımaktadır : it here

yapıştırdım

Şimdi ben bu kodu kullanırsanız aynı JSON ayrıştırmak için:

String response = ConnectionManager.doGet(mAuthType, url, authToken); 
    FLog.d("location object response" + response); 
    //  SimpleModule module = new SimpleModule("UserModule", new Version(1, 0, 0, null, null, null)); 
    //  JsonDeserializer<User> userDeserializer = new Deserializer<User>().getDeserializer(User.class);  
    //  module.addDeserializer(User.class, userDeserializer); 

    ObjectMapper mapper = new ObjectMapper(); 
    //  mapper.registerModule(module); 
    JsonNode tree = mapper.readTree(response); 
    Integer code = Integer.parseInt(tree.get("code").asText().trim()); 

    if(Constants.API_RESPONSE_SUCCESS_CODE == code) { 
     ExploreLocationObject locationObject = mapper.convertValue(tree.path("response").get("locationObject"), ExploreLocationObject.class); 
     FLog.d("locationObject" + locationObject); 
     FLog.d("locationObject events" + locationObject.getEvents().size()); 
     return locationObject; 
    }  
    return null;  

Sonra logcat like this

olduğu Ama aynı JSON için bu kodu kullanırsanız

 String response = ConnectionManager.doGet(mAuthType, url, authToken); 
    FLog.d("location object response" + response); 
    SimpleModule module = new SimpleModule("UserModule", new Version(1, 0, 0, null, null, null)); 
    JsonDeserializer<User> userDeserializer = new Deserializer<User>().getDeserializer(User.class); 

    module.addDeserializer(User.class, userDeserializer); 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.registerModule(module); 
    JsonNode tree = mapper.readTree(response); 
    Integer code = Integer.parseInt(tree.get("code").asText().trim()); 

    if(Constants.API_RESPONSE_SUCCESS_CODE == code) { 
     ExploreLocationObject locationObject = mapper.convertValue(tree.path("response").get("locationObject"), ExploreLocationObject.class); 
     FLog.d("locationObject" + locationObject); 
     FLog.d("locationObject events" + locationObject.getEvents().size()); 
     return locationObject; 
    }  
    return null;   

Sonra logcat olduğunu like this

+0

Bir başka yorum: Eğer yapılmalıdır aşağıdaki kod ile yeniden kullanmak kesinlikle emin 'ObjectMapper' - bir ağır nesnedir ve istek başına bir kez oluşturulan edilmemelidir. Aksi halde çok sayıda GC etkinliğine neden olabilir. Sadece yukarıdaki koddan emin olmak zor. – StaxMan

+0

Aslında, seri hale getiricinizin bir ObjectMapper oluşturduğunu fark ettim: Bu çok masraflıdır. JsonParser kullanarak bunu önleyebilirsiniz.getCodec() ', 'ObjectMapper' (sonuç güvenli yayın) sonucunu verir. Bu da biraz yardımcı olmalı. – StaxMan

+0

Kodumu değiştirdim ve nesne eşleştiriciyi singleton'ma ekledim, performans varsayılan desperizer için geliştirildi, ancak özel deserializer ile ilgili sorun hala var. Ayrıca, aynı modüle iki tane serpiştirici eklediğimde varsayılan desperizatörün özel olanı aramayacağını fark ettim. 'JsonParser.getCodec()' statik bir yöntem değildir, bu nedenle her istek için 'JsonParser' oluşturmam gerekecek. Bu da pahalı olmaz mı? – vKashyap

cevap

2

Nesne ne kadar büyük? Kod temelde bir ağaç modeli (bir tür dom ağacı) oluşturur ve bu, orijinal belge kadar 3x-5x gibi bir şeyi alacaktır. Bu yüzden girişinizin büyük bir JSON belgesi olduğunu varsayalım.

Streaming API kullanarak daha verimli bir sürümü kesinlikle yazabilirsiniz. gibi bir şey: o da mümkündür

JsonParser jp = mapper.getJsonFactory().createJsonParser(input); 
JsonToken t = jp.nextToken(); 
if (t == JsonToken.START_OBJECT) { 
    return mapper.readValue(jp, classToBindTo); 
} 
return null; 

(JsonDeserializer gibi) veri bağlama ile bu uygulamaya ancak biraz sen "varsayılan" deserializer için yetki vermek istediğiniz sırf karmaşık alır. Bunu yapmak için, BeanDeserializerModifier'u uygulamanız ve "modifyDeserializer" çağrıldığında standart seriyi değiştiriciyi değiştirmeniz gerekir: Kendi kodunuz, ara ağaç modelini kullanmak yerine, orijinal serpiştiriciye başvuruyu ve temsilci devredebilir.

+0

Sorumu düzenledim ve JSON'u, ayrıştırma kodunu ve günlükleri ekledim. Teşekkürler – vKashyap

0

Jackson'a bağlı değilseniz, Genson http://code.google.com/p/genson/'u da deneyebilirsiniz. Sizin durumunuzda iki temel avantaj vardır: performansta gevşemezsiniz, uygulanması daha kolay olmalıdır. Mülk etkinliği büyük harfle başlamıyorsa, @JsonProperty ("Olay") ile bir not ekleyiniz (bir üst harfle başlayan diğer özellikler için aynıdır).

Genson genson = new Genson.Builder() 
      .withDeserializerFactory(new EventDeserializerFactory()).create(); 

YourRootClass[] bean = genson.deserialize(json, YourRootClass[].class); 

class EventDeserializerFactory implements Factory<Deserializer<Event>> { 

    public Deserializer<Event> create(Type type, Genson genson) { 
     return new EventDeserializer(genson.getBeanDescriptorFactory().provide(Event.class, 
       genson)); 
    } 

} 

class EventDeserializer implements Deserializer<Event> { 
    private final Deserializer<Event> standardEventDeserializer; 

    public EventDeserializer(Deserializer<Event> standardEventDeserializer) { 
     this.standardEventDeserializer = standardEventDeserializer; 
    } 

    public Event deserialize(ObjectReader reader, Context ctx) throws TransformationException, 
      IOException { 
     if (ValueType.ARRAY == reader.getValueType()) { 
      reader.beginArray().endArray(); 
      return null; 
     } 
     return standardEventDeserializer.deserialize(reader, ctx); 
    } 
} 
+0

Cevabınız için teşekkürler. kesinlikle bir atış verecektir. Ama, atm, ilk olarak jackson ile performansı geliştirmeyi deneyeceğim. – vKashyap

İlgili konular