Hello, "Michael Chelnokov" > > iT>Вот теперь думаю — мог так "сработать" GC или это я где-то ссылки пложу лишние? > А каким образом в managed-коде можно "наплодить лишних ссылок"?
Никаких проблем:
static ArrayList memoryLeakHolder = new ArrayList(); // складывать весь мусор тут
Posted via RSDN NNTP Server 1.8 beta
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Hello, "Igor Trofimov"
> За 7 дней простенький сервер (remoting) сожрал 800 мегов оперативки. Случайно заметили (там еще много памяти было). > > Вот теперь думаю — мог так "сработать" GC или это я где-то ссылки пложу лишние? > > Как бы так посмотреть соотношения тип/кол-во для всех объектов, существующих в памяти приложения? Уже после того, как оно поработало пару дней?
Написать стресс тесты и изначально запустить под профайлером?
Posted via RSDN NNTP Server 1.8 beta
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, Michael Chelnokov, Вы писали:
iT>>Вот теперь думаю — мог так "сработать" GC или это я где-то ссылки пложу лишние?
MC>А каким образом в managed-коде можно "наплодить лишних ссылок"?
Здравствуйте, Igor Trofimov, Вы писали:
iT>За 7 дней простенький сервер (remoting) сожрал 800 мегов оперативки. Случайно заметили (там еще много памяти было).
iT>Вот теперь думаю — мог так "сработать" GC или это я где-то ссылки пложу лишние?
По моему мнению,
Впринципе GC так и должен был сработать, так как сам говоришь что памяти дофига еще оставалось. Просто если система потребует памяти а ее не окажется, тогда пинка под зад даст GC-ру и он начнет шевелится. А так он впринципе правильно что спит — нефиг лишний раз систему нагружать, пока оперативка есть можно и поспать. Потом проснеться почистит за пару сек и снова три дня спать.
Эх мне бы так.
Здравствуйте, Igor Trofimov, Вы писали:
iT>В общем, если кому интересно, вынес я работу с AD в отдельный AppDomain и все стало шоколадно. Поработал — грохнул. Поработал — грохнул.
iT>На досуге надо будет еще проверить на маленьком тесте — действительно ли любое использование AD блокирует сборку мусора или это у меня какое-то особо неприятное стечение обстоятельств было.
Меня тоже посетила эта мысль, но почему-то не помогло. Допускаю, что я по неопытности мог что-то не так сделать с AppDomain, но память из него у меня тоже течет. Мне бы примерчик...
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, Michael Chelnokov, Вы писали:
MC>>А каким образом в managed-коде можно "наплодить лишних ссылок"?
U>Можно забыть отписать объект от события.
Товарищ, бессмертный, можно по подробнее что это значит. Лучше прямо кусок кода. Всмысле делегат создать, "прибавить" к какому-нить событию и не удалить ?
Здравствуйте, Спасибо, Вы писали:
U>>Можно забыть отписать объект от события.
С>Товарищ, бессмертный, можно по подробнее что это значит. Лучше прямо кусок кода. Всмысле делегат создать, "прибавить" к какому-нить событию и не удалить ?
Конечно, можно.
private void menuItem1_Click(object sender, System.EventArgs e)
{
MyClass my = new MyClass(this.Size.Height.ToString());
this.SizeChanged += new EventHandler(my.SizeChanged);
}
public class MyClass
{
public string Name = "";
public MyClass(string name)
{
this.Name = name;
}
public void SizeChanged(object sender, System.EventArgs e)
{
MessageBox.Show(Name);
}
}
При каждом клике на пункт меню будет создавать еще один экземпляр MyClass и умрут они только вместе с формой.
U> private void menuItem1_Click(object sender, System.EventArgs e)
U> {
U> MyClass my = new MyClass(this.Size.Height.ToString());
U> this.SizeChanged += new EventHandler(my.SizeChanged);
U> }
U> public class MyClass
U> {
U> public string Name = "";
U> public MyClass(string name)
U> {
U> this.Name = name;
U> }
U> public void SizeChanged(object sender, System.EventArgs e)
U> {
U> MessageBox.Show(Name);
U> }
U> }
U>
U>При каждом клике на пункт меню будет создавать еще один экземпляр MyClass и умрут они только вместе с формой.
Понятненько. Спасибо !. Я так понимаю можно и просто создать какой-нить public ArrayList в форме , и добавляемые в него элемены не будут отчищаться также до смерти самого приложения ..
Здравствуйте, Спасибо, Вы писали:
С>Понятненько. Спасибо !. Я так понимаю можно и просто создать какой-нить public ArrayList в форме , и добавляемые в него элемены не будут отчищаться также до смерти самого приложения ..
Не совсем, когда создается переменная на уровне формы, то понятно, что она очистится только при закрытии формы. В ситуации с событиями все куда менее прозрачно. Например, в приведенном примере была создана локальная переменная, которая вроде должна уничтожиться при выходе из метода, но на самом деле этого не произойдет.
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, Спасибо, Вы писали:
С>>Понятненько. Спасибо !. Я так понимаю можно и просто создать какой-нить public ArrayList в форме , и добавляемые в него элемены не будут отчищаться также до смерти самого приложения ..
U>Не совсем, когда создается переменная на уровне формы, то понятно, что она очистится только при закрытии формы. В ситуации с событиями все куда менее прозрачно. Например, в приведенном примере была создана локальная переменная, которая вроде должна уничтожиться при выходе из метода, но на самом деле этого не произойдет.
Но она помещалась в вполне нелокальный список (в плане делегат события)
Впринципе событие очень похоже на ArrayList в который складываются делегаты.
Здравствуйте, Igor Trofimov, Вы писали:
iT>За 7 дней простенький сервер (remoting) сожрал 800 мегов оперативки. Случайно заметили (там еще много памяти было).
Здравствуйте, Igor Trofimov, Вы писали:
M>>А с чего ты так решил?
iT>А в TaskManager посмотрели.
В TaskManager посмотрели ты видишь не выделенную а зарезервированную память. Сам не пробовал но читал, что если сложить всю выделеннум память под процессы видимую в
TaskManager то ее будет намного больше. Просто резервируются адреса для дальнейшего использования. Кстати эффект уменьшения памяти в TaskManager можно замечать при сворачивании приложения или воспользоваться SetProcessWorkingSetSize например в http://www.gotdotnet.ru/DotNet/FAQ/CommonForum/524.aspx
А вот если данные манипуляции не помогут то тогда уже рыть ....
и солнце б утром не вставало, когда бы не было меня
зависает на второй строке... отчего это может быть?
2. Выяснилось (спасибо хорошей утильке под названием .net memory profiler), что основной объем памяти отжирает некий System.DirectoryServices.Interop.AdsValueHelper. действительно, прога регулярно обращается к AD, но при этом я делаю using для всего, что шевелится.. тьфу.. для всего, что IDisposable..
Тем не менее этих самых AdsValueHelper накапливается сотни тысяч, они не умирают, и судя по stack trace'ам (которые показывает та же утилька) их создают внутренние механизмы классов DirectoryServices при работе обычных (не IDiposable) SearchResultCollection, .
Что посоветуете? Сталкивался ли кто-то с такой проблемой при работе с AD?
iT>зависает на второй строке... отчего это может быть?
Кстати в этом же номере Джеффри Рихтер http://www.microsoft.com/rus/msdn/magazine/archive/2003-01/dotnet.asp
Как раз рассматривал GC.WaitForPendingFinalizers; при взаимной блокировке.
Скорей всего, чтото в финализаторе блокируется.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Igor Trofimov, Вы писали:
iT>2. Выяснилось (спасибо хорошей утильке под названием .net memory profiler), что основной объем памяти отжирает некий System.DirectoryServices.Interop.AdsValueHelper. действительно, прога регулярно обращается к AD, но при этом я делаю using для всего, что шевелится.. тьфу.. для всего, что IDisposable..
Самое интнресное, что у этого System.DirectoryServices.Interop.AdsValueHelper нет
IDisposable, но есть Finalize который должен перекрываться в наследниках.
S> Самое интнресное, что у этого System.DirectoryServices.Interop.AdsValueHelper нет S>IDisposable, но есть Finalize который должен перекрываться в наследниках.
В каком смысле — "должен перекрываться в наследниках"? Он вроде и так все, что нужно — делает..
Вот только почему-то не умирают эти самые AdsValueHelper'ы ;(
Здравствуйте, Igor Trofimov, Вы писали:
S>> Самое интнресное, что у этого System.DirectoryServices.Interop.AdsValueHelper нет S>>IDisposable, но есть Finalize который должен перекрываться в наследниках.
iT>В каком смысле — "должен перекрываться в наследниках"? Он вроде и так все, что нужно — делает.. iT>Вот только почему-то не умирают эти самые AdsValueHelper'ы ;(
Тогда откуда должен вызываться Finalize, т.к. он протектед.
А вообще он сборочный, а ссылки на него из сборкин нет ни их одного класса.
Надо смотреть откуда он создается.
и солнце б утром не вставало, когда бы не было меня
Finalize вообще-то всегда protected. CLR это не мешает
S> А вообще он сборочный, а ссылки на него из сборкин нет ни их одного класса. S>Надо смотреть откуда он создается.
profiler говорит, что создается он в SearchResultCollection.ResultsEnumerator.GetCurrentResult()
а еще в DirectorySearcher.SetSearchPreferences(...).
Смотрю Reflector'ом — и там и там действительно создается экземпляр этого типа (не потомка), (так что Reflector зря не показывает ссылку на этот тип).
Здравствуйте, Igor Trofimov, Вы писали:
iT>Блин, что же делать? iT>неужели никто не работал массировано с AD и не наталкивался на эти траблы?
Ради подддержания двнного топика...
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Igor Trofimov, Вы писали:
iT>Finalize вообще-то всегда protected. CLR это не мешает
Прошу прощения. Пить мне надо меньше. Конечно же это деструктор, а Finalize формируемый автоматом.
И самое противное, что без IDisposable вызывается только при сборке мусора, и никакие using не помогут.
И здесь интересно
GC.Collect;
GC.WaitForPendingFinalizers;
GC.Collect;
зависает на второй строке... отчего это может быть?
Зависает бог с ним. А после него память высвобождается???
и солнце б утром не вставало, когда бы не было меня
Нужно повключать побольше колонок в Task Manager'е и прикинуть, что вообще каждая из них означает.
Увеличение какого-то показателя не обязательно говорит об утечках и т.п. Это разве что повод задуматься, но не разворачивать бурную деятельность по оптимизации "под TaskManager".
Вообще, трудно диагностируемые утечки бывают к примеру в таких случаях:
Неадекватная работа с COM.
Работа с БД Access.
Непродуманное использование Reflection.Emit, CodeDom и подключаемых сборок-плугинов.
Слишком широкое использование компилируемых регекспов.
Здравствуйте, Igor Trofimov, Вы писали:
S>>И здесь интересно S>> GC.Collect; S>> GC.WaitForPendingFinalizers; S>> GC.Collect; S>> Зависает бог с ним. А после него память высвобождается???
iT>Не-а.
То есть профайлер показывает то же количество этих долбанных объектов????
А если несколько раз коллектнуть???
И в чем могут быть проблемы???
if (this.pinnedHandle.IsAllocated)
{
this.pinnedHandle.Free();
}
или base.Finalize();
и солнце б утром не вставало, когда бы не было меня
iT>зависает на второй строке... отчего это может быть?
Например, в каком-нибудь финализере или Dispose стоит lock. Или что-нибудь похожее на более низком уровне.
Постарайся не разбрасываться объектами по разным потокам, может поможет. На крайний случай можно вообще отдельный AppDomain для продолжительных гнусностей создавать. Оно и ссылки подчистит.
Ага, может они память пинуют и не сразу распинуют?!
Я тут недавно кидал ссылку на похожую проблему в System.Net.Socket, которая будет исправлена в Widbey.
Пока память запинована, GC не может освободить всё, что следует перед этим пинованым указателем в куче. Поэтому не рекомендуется пиноваться слишком часто. Возможно, мелкософтовцы это прохлопали.
В общем, если кому интересно, вынес я работу с AD в отдельный AppDomain и все стало шоколадно. Поработал — грохнул. Поработал — грохнул.
На досуге надо будет еще проверить на маленьком тесте — действительно ли любое использование AD блокирует сборку мусора или это у меня какое-то особо неприятное стечение обстоятельств было.
Здравствуйте, Igor Trofimov, Вы писали:
iT>2. Выяснилось (спасибо хорошей утильке под названием .net memory profiler), что основной объем памяти отжирает некий System.DirectoryServices.Interop.AdsValueHelper. действительно, прога регулярно обращается к AD, но при этом я делаю using для всего, что шевелится.. тьфу.. для всего, что IDisposable..
Млин, ткните носом меня как пользоваться этой "утильке под названием .net memory profiler" .... скачать скачал, как юзать — не въеду
Когда-нибудь и я буду много знать, но пока это не грозит...
ICQ #134433
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Извиняюсь, забыл дописать "... находясь в здравом уме и твердой памяти"
запросто!
public class TestObject
{
public static Instanse = new TestObject();
//....public event Handler SomeEvent;
//....
}
public class TestObject2
{
public void Handler();
}
public void Test()
{
TestObject2 to = new TestObject2();
TestObject.SomeEvent += to.Handler; //все, утечка :) TestObject.Instanse стал для to корнем, и to благополучно тусит в Gen 2 по гроб жизни, отписаться надо :)
}