Вопрос по json, performance, java – GSON Сериализация очень очень медленно

10

Я пытаюсь сериализовать массив из 7000 POJO, используя GSON, и время сериализации очень медленное. Порядка 3-5 секунд для сериализации массива следующего объекта:

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;
}

Ключевые поля сериализуются с использованием настраиваемого сериализатора / десериализатора:

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);
}
}

Чтобы проверить производительность по сравнению с написанием вручную сериализатора JSON, я протестировал следующий код, и он мог сериализовать тот же массив объектов Case примерно в 10 раз быстрее, чем GSON.

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();

Есть идеи, почему GSON так плохо работает в этом случае?

UPDATE

Вот код, который фактически запускает сериализацию:

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

UPDATE2

Вот очень простой тестовый пример, который иллюстрирует низкую производительность по сравнению с org.json:

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));

Где Foo находится:

public class Foo {
public Long id;
}

Это выводит:

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

Разница в производительности почти в 10 раз!

@aloo Да GSON требует очень много времени для инициализации, сериализация / десериализация в порядке, я думаю, экономит время кодирования, а не время выполнения, но инициализация GSON очень медленная. Вы уже нашли решение? Pierre
Я использую gson 2.2, обновляя вопрос кодом, чтобы получить вывод aloo
Как вы создаете свой объект Gson? Jesse Wilson
GsonBuilder gson = new GsonBuilder (); gson.addSerializationExclusionStrategy (new GsonExclusionStrategy ()); gson.registerTypeHierarchyAdapter (Key.class, new GsonKeySerializerDeserializer ()); gson.registerTypeHierarchyAdapter (Date.class, new GsonDateSerializerDeserializer ()); gson.registerTypeHierarchyAdapter (BlobKey.class, новый GsonBlobKeySerializerDeserializer ()); return gson.create (); aloo
Какую версию gson вы используете и какой код вы используете для вывода? Joey

Ваш Ответ

2   ответа
5

тов с нетривиальными данными в них. На моем ThinkPad Gson потребовалось ~ 260 мс для сериализации ~ 3 МБ Gson, что является приличным ~ 10 Мбит / с.

Большая часть этого времени была потрачена на преобразование дат в строки. Преобразование двух полей даты в «длинное»; сэкономлено около 50 мс.

Мне удалось сэкономить еще ~ 10 мс, перенеся с древовидных адаптеров (JsonSerializer / JsonDeserializer) на новый класс потокового адаптера.TypeAdaper, Код, который устанавливает это выглядит следующим образом:

    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();

Основное различие между моим сценарием и вашим заключается в том, что я использую свой собственный фиктивный класс Key. Но если ключ был узким местом, которое должно было возникнуть, когда вы вручную сериализовали каждый случай.

Fixing the problem

Ваш лучший следующий шаг - удалить поля изCase пока сериализация не улучшится. Возможно, что одно из ваших полей содержит что-то, что требует сериализации в течение длительного времени: возможно, очень длинная строка, которая требует чрезмерного экранирования? Как только вы изолируете проблемусообщить об ошибке к проекту Gson, и мы с радостью решим проблему. В дополнение к включениюcode что воспроизводит проблему, вы должны также включить представителяdata.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded aloo
Error: User Rate Limit Exceeded aloo
Error: User Rate Limit Exceeded aloo
Error: User Rate Limit Exceeded aloo

Похожие вопросы