2015-07-20 2 views
1

У меня проблема с созданием String с узла JSON.Медлительность с созданием строки из ObjectNode с помощью Jackson в Java

В настоящее время я делаю это по методу node.toString(). Но иногда это занимает 7-8 секунд, чтобы создать строку JSON с весом 15 МБ-18 МБ.

Я также попытался использовать метод mapper.writeValueAsString(node)). Но это показывает дополнительное время для теста. Это очень сложно проверить проблему, потому что ее также труднее воспроизвести.

В настоящее время я использую только ObjectNode (не TextNode, BooleanNode и т. Д.). Это будет эффект для этого? Или есть лучший способ конвертировать JSONNode в String?

Образец кода: JsonNodeFactory nodeFactory = JsonNodeFactory.instance;

ObjectNode node = nodeFactory.objectNode(); 
node.put("fnm", "Namal"); 
node.put("lnm", "Fernando"); 
node.put("age", 30); 

for (int i = 0; i < 10000; i++) { 

    ObjectNode order = nodeFactory.objectNode(); 
    order.put("id", (i+1000)+""); 
    order.put("nm", "ORD"+(i+1000)); 
    order.put("ref", "RF-"+i); 

    node.put("order"+i, order); 

} 

long smili = System.currentTimeMillis(); 
System.out.println("main().Node : " + node.toString()); 
System.out.println("main().TIMING 1 : " + (System.currentTimeMillis() - smili)/1000.0);; 

long smili2 = System.currentTimeMillis(); 
ObjectMapper mapper = new ObjectMapper(); 

System.out.println("main().Node : " + mapper.writeValueAsString(node)); 
System.out.println("main().TIMING 2 : " + (System.currentTimeMillis() - smili2)/1000.0);; 
+0

Если вы просто измерить один или два элемента, вы выиграли Получите соответствующий результат. Вы должны попробовать хотя бы некоторое h undred или тысячи вызовов для минимизации эффектов загрузки классов, инициализации и т. д. –

+1

В микро-бенчмаркинге есть много деталей. Используйте [специальный инструмент] (http://openjdk.java.net/projects/code-tools/jmh /). – Zernike

+0

@Uwe: Здесь у меня есть формат. И мне в основном нужно знать этот node.toString() - лучший способ для этого или нет. – namalfernandolk

ответ

1

Первые вещи первое: JsonNode.toString() НЕ должен использоваться для сериализации, когда-либо. Он полезен для простого устранения неполадок, но поскольку он не имеет доступа к контекстной конфигурации, он не обязательно будет выдавать действительный JSON. Это по дизайну. Вместо этого вы должны использовать ObjectMapper или ObjectWriter для его сериализации; это приведет к действительному JSON, используя точную конфигурацию и настройки, которые имеет картер (или создатель, созданный картографом).

Теперь ваше сравнение времени является ошибочным, так как вы делаете только один звонок с ObjectMapper. В первых N вызовах есть накладные расходы; частично из-за инициализации ObjectMapper, частично из-за прогрева JVM (динамический JIT-компилятор работает для оптимизации и т. д.). Чтобы получить больше полезных результатов, вам нужно будет вызвать метод несколько раз, и в идеале пусть он будет работать в течение нескольких секунд.

Но помимо этого, общая проблема заключается в том, чтобы забыть иметь достаточно пустое пространство. В Java для строк требуется память как минимум эквивалентная 2x длине строки в символах (каждый char занимает 2 байта). Но это только размер результата; во время сериализации также необходим временный буфер, используя примерно сопоставимую сумму. На диске, однако, кодировка UTF-8 обычно использует только 1 байт на символ (для символов ASCII).

Предположим, что вы видите файл размером 15 мБ, он может использовать 60 мБ памяти во время обработки. Если размер вашей кучи установлен на маленький (скажем, 64 мегабайта, который по умолчанию используется во многих случаях), это приведет к очень тяжелой обработке мусора. Решение было бы либо увеличить размер кучи. Или, если вы на самом деле не нужна String, чтобы:

  1. запись непосредственно в файл: использование промежуточного String является анти-модель, если результат переходит в File или сетевое соединение
  2. Если вам требуется промежуточная форма , сериализации, как byte[]: это нужно будет только такой же объем памяти, как файл будет (так как это UTF-8 закодированы в памяти, вместо того, чтобы быть обернуты char[]
+0

Спасибо StaxMan. Это очень информативно и очень полезно. Я изменил его на objectMapper.writeValue (wr, availabilityNode); Теперь нужно протестировать в «Производство» после маркировки стендов. Еще раз спасибо. – namalfernandolk

+0

@Namalak добро пожаловать! – StaxMan

Смежные вопросы