Я пытаюсь загрузить около 5 миллионов объектов, извлеченных из DB через спящий режим в хэш-карту. Я делаю это для двух типов классов (A & B). Я прохожу через поля. Ключ - поле из pojo, а значение - сами pojo.
1. Для класса A ключ является целым полем. Я могу загрузить карту менее чем за 20 секунд.
Для класса B
2.a) Тест 1, мой ключ является строковым полем. Когда я пытаюсь загрузить эти объекты в новый hashmap (новая попытка перезапуска java-процесса, так что никакого внимания с GC еще нет), для загрузки на карту 100K объектов требуется около 30 секунд.
2.b) Тест 2, когда я пытаюсь использовать другое поле этого класса (целочисленного типа) и загружать карту, он работает как 1-й и загружается менее чем за 20 секунд.
2.c) Тест 3, я задавался вопросом, была ли проблема типом данных. Итак, для класса B я попробовал другой подход к созданию строкового ключа с использованием целочисленного поля в # 2.b. (key = int_field + "") и загружается в < 20 секунд.Производительность Hashmap put зависит от ключей
Еще один тест, тест 4, который я сделал для класса типа B, - это способ, которым я создал ключ. Для 2.c я создал такой ключ
map.put (pojo.getIntField() + "", pojo);
Результат был, как упоминалось выше, в 2.c
2.d) Но когда я создал еще один поглотитель в POJO, что возвращаемый int_field + «» и использовал это в карте положить в
map.put (pojo.getIntFieldInStringForm(), pojo);
Производительность ухудшилась примерно до 30 секунд для объектов 100K.
Я знаю, что проблема связана с ключами, потому что я проверил фазу выборки db, добавив объекты результата в список и загрузив ее в < 20 секунд для обоих типов.
Я не могу понять причину этого. Если кто-то может пролить свет на это, это будет очень полезно. Очень признателен. Благодаря
Отредактировано: Добавление фрагменты кода здесь (простите форматирование/опечаток если таковые имеются):
Тест на # 1
Map<String, ClassA> map = new HashMap<String, ClassA>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassA> iterator = session.createQuery("from ClassA").setFetchSize(1000).iterate();
while (iterator.hasNext()) {
ClassB objClassA = iterator.next();
map.put(objClassB.getIntField(), objClassA);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
Тест на # 2.а
Map<String, ClassB> map = new HashMap<String, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery("from ClassB").setFetchSize(1000).iterate();
while (iterator.hasNext()) {
ClassB objClassB = iterator.next();
map.put(objClassB.getStringField(), objClassB);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
Тест на # 2.b
Map<Integer, ClassB> map = new HashMap<Integer, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery("from ClassB").setFetchSize(1000).iterate();
while (iterator.hasNext()) {
ClassB objClassB = iterator.next();
map.put(objClassB.getIntField(), objClassB);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
тест для # 2.c
Map<String, ClassB> map = new HashMap<String, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery("from ClassB").setFetchSize(1000).iterate();
while (iterator.hasNext()) {
ClassB objClassB = iterator.next();
map.put(objClassB.getIntField() + "", objClassB);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
тест для # 2.d
Map<String, ClassB> map = new HashMap<String, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery("from ClassB").setFetchSize(1000).iterate();
while (iterator.hasNext()) {
ClassB objClassB = iterator.next();
map.put(objClassB.getIntFieldInStringForm() + "", objClassB);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
Выполнение 'string + string' создает новый' StringBuilder', если он уже не обрабатывает операцию concat, так что это может повредить производительность, если вы делаете это совсем немного в цикле. Вместо этого используйте 'Integer.toString (int)'. Просто подсказка. Далее: насколько велики объекты 'String', которые вы загружаете из db? –
Зачем вам делать '+" "' после 'getIntFieldInStringForm()', когда значение уже является строкой? --- Если производительность важна для вас, замените 'getIntField() +" "' на 'Integer.toString (getIntField())'. --- В 2a, насколько велики строки? – Andreas
Мы не можем видеть, что вы делаете в своих тестовых корпусах. Создайте небольшой тестовый файл, который воспроизводит эту проблему. Или как в официальной закрытой причине: вопросы, требующие помощи по отладке («почему этот код не работает?») Должны включать в себя желаемое поведение, конкретную проблему или ошибку и кратчайший код, необходимый для воспроизведения в самом вопросе. Вопросы без четкого описания проблемы не полезны другим читателям. См.: Как создать минимальный, полный и проверенный пример. –