![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| IDVsbruck |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 778 Регистрация: 12.11.2006 Репутация: нет Всего: 22 |
У меня достаточно простая программка - парсинг XML и занесение данных в БД.
Размер тестируемого XML - около 8 Мб, суммарно добавляется около 20-22 тыс. записей. При работе памяти, стандартно выделенной JVR, не хватает. Добавлять параметры в строку запуска не хочу, да и не могу - проект будет раниться на разных машинах в разных местах и размер XML файла неизвестен - от сотен байт до десятков мегабайт, нет гарантии, что даже при большой выделенной памяти он рано или поздно не выдаст OutOfMemoryError. Вручную перелопатил код взад и вперед - за один проход цикла добавляет суммарно от 10 до 40 Кб. За несколько сотен проходов съедает все. Практически все вычисления вынес в вызываемые статические методы, но после возврата из них память уменьшается. И хотя это позволило завершить на моей машине работу, но это было как каз впритык ... Скачал и установил JProfiler. Юзаю, юзаю Спасибо. |
|||
|
||||
| y3u |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 440 Регистрация: 9.9.2006 Где: Москва Репутация: 1 Всего: 13 |
Попробуй использовать какой-нибудь кеш. Небось все дерево в памяти держишь?
-------------------- В нашей стране настаивать на кореньях, черной смородине, лимонных корках - гораздо эффективнее, чем на правах |
|||
|
||||
| IDVsbruck |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 778 Регистрация: 12.11.2006 Репутация: нет Всего: 22 |
Возможно, что все дерево висит в памяти, но тогда все же направшивается вопрос - почему идет утечка памяти?
Путем проверки памяти на каждом этапе выполнения программы выяснил, что утечка как раз идет не при парсинге, а при записи в базу, что особенно странно. Скажем, в main() вызываю свои методы, которые получают и обрабатывают данные из Документа, и выдают значения. Проверка показала, что память до и после получения равна. Далее вызыватся метод, который заносит данные в БД (упрощено):
Память съедается именно при обновлениях данных (resultSet.updateString(), resultSet.updateInt() и т.д.) - то есть при каждом апдейте доступная память уменьшается, какой остается при возврате из вызванного метода. Переменные connection и resultSet пробовал делать как локальными, так и глобальными - результат идентичный ... |
|||
|
||||
| w1nd |
|
|||
![]() Вертилятор ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1077 Регистрация: 22.3.2006 Где: Москва Репутация: 2 Всего: 54 |
Именно так. Строки лучше при всяком удобном случае конструировать заново (даже явно). -------------------- ![]() ![]() |
|||
|
||||
| IDVsbruck |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 778 Регистрация: 12.11.2006 Репутация: нет Всего: 22 |
Строки ... конструировать?
... инстансы ... где они? Чу-у-уточку попдробнее, я, видимо, вас не сильно понимаю .... |
|||
|
||||
| y3u |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 440 Регистрация: 9.9.2006 Где: Москва Репутация: 1 Всего: 13 |
ну, на ум сразу приходит мысль по поводу коннектора. Что за БД, что за коннектор? У меня была ситуация, когда некий коннектор под MSSQL срал нещадно во временную директорию винды - создавал там нереальное количество каких-то временных файлов, всвязи с чем у меня были проблемы и с памятью и с работой с БД - дело решилось заменой коннектора. ну это так, были общие мысли... ПыСЫ кстати, для проверки наличия чего бы то ни было, лучше использовать запросы для этого предназначенные SELECT COUNT всякий там... А вместо "INSERT INTO names (company, f2, f3) VALUES ('" + _f1 + "', '" + _f2 + "', '" + _f3 + "')"; нравственней бы было использовать PreparedStatement -------------------- В нашей стране настаивать на кореньях, черной смородине, лимонных корках - гораздо эффективнее, чем на правах |
|||
|
||||
| IDVsbruck |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 778 Регистрация: 12.11.2006 Репутация: нет Всего: 22 |
Заремарил все обращения к БД (потери идут не всегда - раз в 3-4 обращения к базе (???) - видимо, действительно, драйвер барахлит), но утечка осталась практически на том же уровне.
Стал построчно проверять память. Это, конечно, дико, но единственное (!!!) место при прохождении по дереву XML, где теряется память - это выражение myNodeList.getLength(), вне зависимости от его расположения - в условиях цикла или при определении интовской переменной. Вот такие вот глюки в пакете org.w3c.dom - это уже стандартными средствами не исправишь! Одно радует - есть возможность обходить поддерево не через NodeList и его метод getLength(), а через метод Node - getNextSibling() - итерациями. Возможно, кто-то когда-то сталкивался с подобной "ерундой". Странно, что я нигде не встречал в инете даже упоминания о подобном глюке ... З.Ы. Драйвер - sun.jdbc.odbc.JdbcOdbcDriver Это сообщение отредактировал(а) IDVsbruck - 20.2.2007, 16:10 |
|||
|
||||
| y3u |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 440 Регистрация: 9.9.2006 Где: Москва Репутация: 1 Всего: 13 |
а ты как, в for цикле небось обходил? скорее всего в этой имплементации - это вычисляемая функция, а ты, небось ее на каждой итерации в for дергал, попробуй либо написать for (int i = 0, j = myNodeList.getLength(); i < j; i++), либо, действительно, возьми другую-нибудь другую имплементацию заточенную для работы с большими XML-никами
ПыСы А нафига тебе ODBC мост? С любой нормальной БД можно напрямую работать - уже коннекторов развелось полно. Или ты какой-нибудь Access или Excell используешь? Это сообщение отредактировал(а) y3u - 20.2.2007, 18:31 -------------------- В нашей стране настаивать на кореньях, черной смородине, лимонных корках - гораздо эффективнее, чем на правах |
|||
|
||||
| IDVsbruck |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 778 Регистрация: 12.11.2006 Репутация: нет Всего: 22 |
Вариант for (int i = 0, j = myNodeList.getLength(); i < j; i++) я привел - он так же "кушает", и вообще, любое обращение к getLength() НЕ возвращает память.
Видимо, действительно лучше подключить внешнюю библиотеку, работающую с большими XML-ми. Что наименее громоздко и наиболее удобно? З.Ы. |
|||
|
||||
| LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 15 Всего: 538 |
1. Ты не пробовал обновить JDK? 2. Попробуй Xerces, во всяком случае исходники у него есть и API совпадает с JAXP. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
| IDVsbruck |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 778 Регистрация: 12.11.2006 Репутация: нет Всего: 22 |
Хочу закрыть тему ...
Мои слабые знания на момент возникновения данной темы не позволили мне сразу разобраться в проблеме. Действительно, дело в DOM парсере и как таковой "утечки памяти" не наблюдается. При парсинге моего 8-ми Мб-тового XML-файла DOM-парсер создал структуру, которая "легла" в памяти на 46 Мб. Так как первоначально в Document находится только структура, то по мере анализа ее и чтения данных они также помещаются в память. Выполнив ~80% работы, DOM-документ стал занимать в памяти ~64 Мб, после чего выдал злостную ошибку OutOfMemoryError. Видимо, это и есть доступная по умолчанию память для проекта, выделяемая JVM. Единственным не совсем понятным для меня моментом стала такая ситуация: в private методе создаем Документ, парсим в него XML, закрываем поток, обнуляем Документ (null), возвращаемся в вызывающий метод ... а память остается на прежнем уровне. Но, по всей видимости, как об этом пишут источники, это не проблема с проектом, а "неспешная" работа Garbage Collector (Cleaner?) - он просто не успевает до конца выполнения проекта очистить память, так как на нее "пока никто не зарится". Естественно, проблему решил с помощью технологии SAX - не так просто и наглядно как DOM, но очень шустро и с минимальными затратами памяти. Пик загрузки памяти у меня был ~845 Кб. Большое спасибо за советы. |
|||
|
||||
| LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 15 Всего: 538 |
GC будет вызываться по мере нобходимости, или его надо вызвать самому System.gc(). Но это не означает, что сразу вся память будет возвращена ОС. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java tools & IDE's | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |