加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – GSON序列化非常慢

发布时间:2020-12-14 16:38:43 所属栏目:Java 来源:网络整理
导读:我试图使用GSON序列化一个7000 POJO阵列,并且序列化时间非常慢.序列化以下对象的数组是3-5秒的顺序: public class Case { private Long caseId; private KeyOrganization orgKey; private KeyWorkflow workflowKey; private KeyUser creatorKey; private Da
我试图使用GSON序列化一个7000 POJO阵列,并且序列化时间非常慢.序列化以下对象的数组是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,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对象数组序列化大约比GSON快10倍.

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倍的性能差异!

解决方法

我试图重现你的问题,不能.我在其中创建了7000个具有非平凡数据的对象.在我的ThinkPad上,Gson?260ms串行化?3MB的Gson,这是一个可观的?10Mbps.

大部分时间用于将日期转换为字符串.将两个日期字段转换为“长”保存约50ms.

通过从树型适配器(JsonSerializer / JsonDeserializer)迁移到新的流式适配器ClassAdaper类,我可以保存另外约10ms.设置此代码的代码如下所示:

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类.但是,如果Key是手动序列化每个案例时应该出现的瓶颈.

解决问题

最好的下一步是从Case中删除字段,直到序列化改进.您的一个字段可能包含长时间序列化的东西:也许是一个需要过多转义的长字符串?一旦将问题report a bug与Gson项目隔离开来,我们将很乐意解决问题.除了包含重现问题的代码之外,还应包括代表性数据.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读