Здравствуйте, D.Triton, Вы писали:
DT>Каким образом можно явно освободить память в .net 1.1.
... DT>Что можете посоветовать? Что почитать и где посмотреть. Самые явные ошибки, которые я мог допустить?
А что, все так плохо с памятью или это просто истерика из-за лишнего десятка мегобайт "черезмерно" отъедаемого программой из полугига доступных?
Дело в том, что, возможно, память была очищена, но не возвращена в систему. Это нормальная ситуация в .NET приложении — оно хапает много памяти про запас, потом спокойно ею пользуется. После вызова GC она может получить почти пустую кучу — для нее — но с точки зрения системы эта память занята — и в таск менеджере будет показываться, что прилада ее занимает. А сама прилада эту память в систему не отдает, поскольку считает, что она ей и самой еще пригодится для дальнейшей работы (затребовать память у операционки — занимает время). Особенно характерно это проявляется когда в системе много свободной памяти.
Здравствуйте, fmiracle, Вы писали:
F>Здравствуйте, D.Triton, Вы писали:
DT>>Каким образом можно явно освободить память в .net 1.1. F>... DT>>Что можете посоветовать? Что почитать и где посмотреть. Самые явные ошибки, которые я мог допустить?
F>А что, все так плохо с памятью или это просто истерика из-за лишнего десятка мегобайт "черезмерно" отъедаемого программой из полугига доступных?
F>Дело в том, что, возможно, память была очищена, но не возвращена в систему. Это нормальная ситуация в .NET приложении — оно хапает много памяти про запас, потом спокойно ею пользуется. После вызова GC она может получить почти пустую кучу — для нее — но с точки зрения системы эта память занята — и в таск менеджере будет показываться, что прилада ее занимает. А сама прилада эту память в систему не отдает, поскольку считает, что она ей и самой еще пригодится для дальнейшей работы (затребовать память у операционки — занимает время). Особенно характерно это проявляется когда в системе много свободной памяти.
Вообщем-то не 10, а 1.6 -2 гига.
Мы парсим огромный текстовый файл. вот после этих операций парсинга и происходит "утечка" памяти.
Комп свапиться начинает. Но вызов GC.Collect(), что я описа выше, ничего не дает
DT>>>Каким образом можно явно освободить память в .net 1.1.
Хм, вот под FW 1.1 сказать не могу, а случае 2.0 и large block of unmanaged memory можно было бы глянуть на MemoryPressure, в частности методы: GC.AddMemoryPressure и GC.RemoveMemoryPressure.
Здравствуйте, D.Triton, Вы писали:
DT>Здравствуйте, fmiracle, Вы писали:
F>>Здравствуйте, D.Triton, Вы писали:
DT>>>Каким образом можно явно освободить память в .net 1.1. F>>... DT>>>Что можете посоветовать? Что почитать и где посмотреть. Самые явные ошибки, которые я мог допустить?
F>>А что, все так плохо с памятью или это просто истерика из-за лишнего десятка мегобайт "черезмерно" отъедаемого программой из полугига доступных?
F>>Дело в том, что, возможно, память была очищена, но не возвращена в систему. Это нормальная ситуация в .NET приложении — оно хапает много памяти про запас, потом спокойно ею пользуется. После вызова GC она может получить почти пустую кучу — для нее — но с точки зрения системы эта память занята — и в таск менеджере будет показываться, что прилада ее занимает. А сама прилада эту память в систему не отдает, поскольку считает, что она ей и самой еще пригодится для дальнейшей работы (затребовать память у операционки — занимает время). Особенно характерно это проявляется когда в системе много свободной памяти.
DT>Вообщем-то не 10, а 1.6 -2 гига. DT>Мы парсим огромный текстовый файл. вот после этих операций парсинга и происходит "утечка" памяти.
DT>Комп свапиться начинает. Но вызов GC.Collect(), что я описа выше, ничего не дает
Скажите, может быть в течение работы Вашего приложения создается много мелких долгоживущих объектов? Они постепенно перекочуют во 2-ое поколение и могут там очень долго жить... GC может не убирать 2-ое поколение, пока не заполнится первое. Учитывая это + адаптивность размера поколений (то есть размер поколения может изменяться) можем получить Ваш случай...
Похожую картину (по количеству использованной памяти) можно наблюдать при парсинге большого (N x 100MB) XML файла с построением DOM. Если есть возмжность, можно попробовать перейти на read only + forward only режим парсинга (как SAX для XML).
Еще одна возможная причина — какие-то объекты остались подписаны на события...
А целом, как сказал выше Mab воспользуйтесь профайлером.
Здравствуйте, pt4h, Вы писали:
P>Скажите, может быть в течение работы Вашего приложения создается много мелких долгоживущих объектов? Они постепенно перекочуют во 2-ое поколение и могут там очень долго жить... GC может не убирать 2-ое поколение, пока не заполнится первое. Учитывая это + адаптивность размера поколений (то есть размер поколения может изменяться) можем получить Ваш случай... P>Похожую картину (по количеству использованной памяти) можно наблюдать при парсинге большого (N x 100MB) XML файла с построением DOM. Если есть возмжность, можно попробовать перейти на read only + forward only режим парсинга (как SAX для XML).
P>Еще одна возможная причина — какие-то объекты остались подписаны на события...
P>А целом, как сказал выше Mab воспользуйтесь профайлером.
У меня появилась идея, но как-то она не очень нравится мне.
Что, если код парсинга перевести на чистый с++, там то я точно могу управлять памятью?
Стоит ли так поступать или нет? Вернее переходил ли кто-либо на с++ ради управления памяти (для отдельных алгоритмов).
По поводу 2-го поколения,
GC.Collect() аналогичен GC.Collect(2).
Так,что по 2-му поколению GC должен тоже "прогуляться".
Проблемма не только в парсинге. Когда я закачиваю данные в DevExpress Grid Control, то по закрытию формы данные не освобождаются также.
Ну во всяком случае за приемлимое время.
Ну с тем не так важно. А вот при парсинге проблемма. Просто на меня таск выставили, оптимизировать работу приложения с памятью. Мы эту прогу год почти пишем. Уже она (прога) стала солидненькой, жирком обросла. И ходить и оптимизировать все алгоритмя ломает.
Быстрым решением было бы переложить все на Garbage Collector, да вот он похоже ведет себя как сам захочет
Вот с профайлером поковыряться надо это факт. Правда сначала надо понять как им вообще пользоваться
Здравствуйте, D.Triton, Вы писали:
DT>У меня появилась идея, но как-то она не очень нравится мне. DT>Что, если код парсинга перевести на чистый с++, там то я точно могу управлять памятью? DT>Стоит ли так поступать или нет? Вернее переходил ли кто-либо на с++ ради управления памяти (для отдельных алгоритмов).
Я лично не делал, хотя не исключаю такой возможности.
Могу только сказать.ч то сам по себе парсинг огромных файлов не вызывает проблем в .NET и GC справляется.
Другое дело — как организован алгоритм. Видимо, там использовалось какое-то не очень удачное для именно больших файлов решение.
Пока не увидим — ничего сказать не сможем. Попробуй действительно поигратсья профайлерами...
Здравствуйте, D.Triton, Вы писали:
DT>Вообщем-то не 10, а 1.6 -2 гига. DT>Мы парсим огромный текстовый файл. вот после этих операций парсинга и происходит "утечка" памяти.
DT>Комп свапиться начинает. Но вызов GC.Collect(), что я описа выше, ничего не дает
Это симптомы того, что у вас в коде где-то происходит накопление данных. GC тут не при чём. Ищите места где вы складируете ваши данные и в дальнейшем их так и продолжаете держать. Послушайте что говорит Mab, возмите профайлер.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, D.Triton, Вы писали:
DT>По закрытию окна, на котором расположен DataGrid данные не освобождаются даже DT>с помощью DT>GC.Collect(); DT>GC.WaitForPendingFinalizers(); DT>GC.Collect(); DT>Что можете посоветовать? Что почитать и где посмотреть. Самые явные ошибки, которые я мог допустить? DT>К стати, по закрытию окна метод Dispose у формы вызывается.
Скорее всего, Вы положили ссылку (прямую или косвенную) на Ваши данные в статическое поле какого-то класса. Если есть ссылка из статического поля, то никакой GC.Collect() не поможет. Dispose тоже скорее всего не трогает статические поля, потому что он — экземплярный метод.
Здравствуйте, nikov, Вы писали:
N>Здравствуйте, D.Triton, Вы писали:
N>Скорее всего, Вы положили ссылку (прямую или косвенную) на Ваши данные в статическое поле какого-то класса. Если есть ссылка из статического поля, то никакой GC.Collect() не поможет. Dispose тоже скорее всего не трогает статические поля, потому что он — экземплярный метод.
Согласен, но что тогда делать с DevExpress формой (вернее ее потомком) и GridControl?
Я думаю, что данные там-то должны освобождаться нормально. Я же всего-навсего зафилил датасет и подсунул его Гриду.
Потом закрыл форму. У нее даже Dispose() вызвался Но память не освободилась.
У меня тут мысль пробежала. После удаления объектов из памяти GC производит ее дефрагментацию. Однако он не трогает "большие объекты".
Может быть в этом и есть дело. Может указатель NextObject не опускается в Хипе ниже этого большого объекта (формы со всем тем барахлом, что я в нее всунул)?
DT>РАБОТАЕТ!!!! Только чего оно делает-то? :)
DT>Спасибо огромное!!!!!
Собственно говоря мы ручками удаляем мусор...
EmptyWorkingSet The EmptyWorkingSet function removes as many pages as possible from the working set of the specified process.
BOOL EmptyWorkingSet(
HANDLE hProcess // identifies the process
);
Parameters
hProcess
Handle to the process.
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Remarks
You can also use the SetProcessWorkingSetSize function to do what EmptyWorkingSet does if you pass it 0xFFFFFFFF for the minimum and maximum sizes.
See Also
Process Status Helper Overview, PSAPI Functions, EnumProcesses, SetProcessWorkingSetSize
Дело в том, что, возможно, память была очищена, но не возвращена в систему. Это нормальная ситуация в .NET приложении — оно хапает много памяти про запас, потом спокойно ею пользуется. После вызова GC она может получить почти пустую кучу — для нее — но с точки зрения системы эта память занята — и в таск менеджере будет показываться, что прилада ее занимает. А сама прилада эту память в систему не отдает, поскольку считает, что она ей и самой еще пригодится для дальнейшей работы (затребовать память у операционки — занимает время). Особенно характерно это проявляется когда в системе много свободной памяти.
Только надо отметить что память системе будет возвращена, если ей она потребуется.
PS. Освобождение workinkset'a можно добится если свернуть прилржение.
DT>Что, если код парсинга перевести на чистый с++, там то я точно могу управлять памятью? DT>Стоит ли так поступать или нет? Вернее переходил ли кто-либо на с++ ради управления памяти (для отдельных алгоритмов).
изучал много различных Toolkits связанных с графикой, везде так и сделано.