2017-01-05 5 views
2

Интересно, может ли кто-нибудь объяснить, что происходит с моим кодом. У меня есть IgniteCache Long-> Object [], который является своего рода механизмом пакетной обработки.Незначительное использование памяти при использовании CacheEntryProcessor и изменение ввода кэша

Кэш отключен, секционирован и имеет одну резервную копию.

Я хочу изменить некоторые объекты в массиве значений записи кэша. Так что я написал и реализация CacheEntryProcessor

@Override 
    public Object process(MutableEntry<Long, Object[]> entry, Object... arguments) 
        throws EntryProcessorException { 
     boolean updated = false; 
     int key = (int)arguments[0]; 
     Set<Long> someIds = Ignition.ignite().cluster().nodeLocalMap().get(key); 

     Object[] values = entry.getValue(); 
     for (int i = 0; i < values.length; i++) { 
      Person p = (Person) values[i]; 
      if (someIds.contains(p.getId())) { 
       p.modify(); 
       if (!updated) { 
        updated = true; 
       } 
      } 
     } 
     if (updated) { 
      entry.setValue(values); 
     } 
     return null; 
    } 
} 

Когда кластер загружается с данными каждый узел потребляет около 20GB кучи. Когда я запускаю процессор кэша с cache.invokeAll на кластере с несколькими узлами, у меня сумасшедшая память - когда процессор запускается, я вижу, что использование памяти увеличивается до 48 ГБ или выше, что в конечном итоге приводит к разделению узлов из кластера. слишком долго.

Однако, если я удаляю строку entry.setValue(values), которая хранит обратно измененный массив в кеш, все в порядке, за исключением того факта, что данные не будут реплицироваться, так как кэш не знает об этом изменении - обновление виден только на основном узле :(

Может кто-нибудь сказать мне, как заставить его работать? что не так с этим подходом?

ответ

0

Прежде всего, я бы не рекомендовал выделять большие размеры кучи. Это будет очень вероятно, вызовет длительную паузу GC, даже если все работает правильно. В принципе, JVM не будет очищать память до тех пор, пока она не достигнет определенного порога, и когда она достигнет, будет много мусора для col Lect. Попробуйте переключиться на кучу или запустить больше узлов Ignite.

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

Если это не помогает, возьмите кучу кучи и проверьте, что занимает память.

+0

Конечно, я знаю о различных проблемах при использовании больших куч, но до сих пор это не было большой проблемой для нас. Мы запускаем на карте памяти сокращения заданий, которые создают некоторую статистику по объектам, хранящимся в кеш-на-куче, были просто быстрее, чем у кучи при той же настройке аппаратного обеспечения - мы всегда проверяем все данные. Можете ли вы объяснить, как entry.setValue работает внутри? Что происходит за этим звонком? Для меня похоже, что где-то есть копия созданного или сериализованного объекта, я заметил, что объекты, появляющиеся сразу в старом гене (должны быть из-за их размеров). – Bart

+0

Запрашиваю, потому что я изменяю исходный массив и не создаю новые объекты и сохраняю их через setValue. Согласно коду setValue он присваивает oldVal предыдущему значению и val к ​​новому, поэтому мне интересно, откуда берутся новые объекты. – Bart

+1

Да, копия создается, когда вы получаете значение, а 'setValue' заменяет старое значение новым. –

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

  • Нет связанных вопросов^_^