Текущие классы, загруженные постоянно увеличение - утечка памяти

Часто бывает удобно включить столбец «глубины» в такие запросы:

WITH recursive subdomains AS (
      SELECT id, parent_id, domain, 1 as lev
      FROM domains
      WHERE id = '42b2af32-21a0-4212-b634-19ec47982e6b'
      UNION ALL
      SELECT d.id, d.parent_id, d.domain, s.lev + 1
      FROM domains d INNER JOIN
           subdomains s
           ON s.parent_id::text = d.id::text  -- is type conversion really necessary?
     )
SELECT s.*
FROM subdomains s;

Если я правильно понимаю, вы можете просто добавить ORDER BY lev DESC в окончательный запрос.

6
задан Page 5 December 2008 в 14:19
поделиться

9 ответов

Я полагаю, что проблема была на самом деле вызвана серией не склонных экземпляров FileSystemWatcher, которые были вложенным путем вниз в RemoteTaskRunner MBRO. Я все еще не уверен, что разрешил утечку памяти полностью, но я могу определенно сказать различие.

Кажется, что это не первый раз, когда FileSystemWatchers вызвали меня проблемы.:)

Спасибо все (особенно leppie) для помощи мне с этим!

2
ответ дан 10 December 2019 в 00:46
поделиться

Этот .net 2.0 или выше? Если так, Вы не можете разгружаться AppDomain (как Jon Skeet говорит в комментарии).

Если это 1.1 или ниже, существует ошибка в AppDomain разгрузите функциональность. Т.е. это не освобождает память или высвобождает средства когда AppDomain "разгружен".

(Это было зафиксировано с .net 2.0),

2
ответ дан 10 December 2019 в 00:46
поделиться

Можно всегда проверять, какие блоки загружаются в AppDomain:

foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
      Console.WriteLine(assembly.FullName);
}

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

Править:

если Вы хотите использовать WinDgb SOS, вот поддерживаемые команды. Вы, скорее всего, интересуетесь: DumpDomain, DumpClass, DumpAssembly, EEHeap...

2
ответ дан 10 December 2019 в 00:46
поделиться

Я предложил бы использовать надлежащего профилировщика памяти - как "Профилировщик Памяти.NET" - http://memprofiler.com/, который можно, конечно, испытать его на оценке, чтобы видеть, является ли это вид инструмента, который поможет.

Это позволит Вам видеть все живые объекты намного более легко, чем жесткий материал WinDBG/SoS.

1
ответ дан 10 December 2019 в 00:46
поделиться

Как сказано другим ответом, AppDomain. Разгрузитесь (), должен использоваться.

Однако необходимо быть осторожными, Вы не загружаете блоки в нескольких местах, особенно основной appdomain.

Посмотрите на документы MSDN для AppDomain. Загрузка (AssemblyName) для объяснения того, как вышеупомянутое происходит.

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

1
ответ дан 10 December 2019 в 00:46
поделиться

Я просто считал это на блоге Suzanne Cook.

http://blogs.msdn.com/suzcook/archive/2003/06/12/57169.aspx

Обязательно не передайте любой Тип/Блок/и т.д. экземпляры (помимо Вашего типа MarshalByRefObject) назад к исходному appdomain. Если Вы сделаете, то это заставит те блоки быть загруженными в исходный appdomain. Если appdomain настройки отличаются между двумя appdomains, те блоки не могут быть загружаемыми там. Плюс, даже если они успешно загружаются, блоки останутся загруженными и заблокированными после того, как цель appdomain будет разгружена, даже если исходный appdomain никогда не использует их.

Когда она говорит любой Тип/Блок/и т.д. Что делает она может КАКОЙ-ЛИБО тип? Причина, которую я спрашиваю, то, потому что мой MarshalByRefObject (RemoteTaskRunner) действительно возвращает объект DateTime назад после выполнений задачи. Это могло заставить сменный блок быть загруженным в мой основной appDomain (и в конечном счете вызвать утечку памяти)?

1
ответ дан 10 December 2019 в 00:46
поделиться

Я всегда бросаю это там, каждый раз, когда кто-то сообщает об утечке памяти, потому что она заставляла меня напряженно трудиться в течение пары недель. Не запускайте свое приложение в режиме отладки. Если Вы запускаете свое приложение в режиме отладки в.Net 2.0 + (не произошел в.Net 1.1), и Вы инстанцируете класса, который содержит событие, даже если Вы не сгенерируете событие, то это будет содержать только маленькую часть памяти. Это может значительно произвести длительные приложения, такие как сервисы и веб-приложения, потому что со временем небольшой объем памяти, съеденной после инстанцирования объектов, может составить в целом довольно много.

1
ответ дан 10 December 2019 в 00:46
поделиться

Править: После чтения некоторых из других сообщений они должны быть учтены после того, как лучший профилировщик используется и после того, как в проблеме appDomain разбираются.

Можно хотеть добавить счетчики производительности на службу так, по крайней мере, объекты, которые Вы создаете, может быть прослежен. Это поможет Вам определить если Классы. Загруженный являются Вашими, или классы CLR.

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

Как последнее прибежище можно попытаться поместить GC.Collect () там, чтобы видеть, если вызов его исправляет проблему. Не фиксация, но тестирование это сообщит, что это - опция.

0
ответ дан 10 December 2019 в 00:46
поделиться

AppDomains разгружены, но ответ от leppie, заставляет меня задаться вопросом, загружаются ли сменные блоки и в Основной AppDomain и во вторичный AppDomain. Когда я смотрю на счетчики производительности, текущее количество AppDomain постоянно не увеличивается.

Приложение, как предполагается, создает Вторичный appDomain и затем загружает отдельный сменный блок. Возможно, некоторый код помог бы:

Создание вторичного AppDomain от основного appDomain:

AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationName = "RemoteAgentLib";
ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
ads.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory;
ads.ShadowCopyDirectories = AppDomain.CurrentDomain.BaseDirectory;
ads.ShadowCopyFiles = "true";

m_domain = AppDomain.CreateDomain("RemoteTaskRunner", null, ads);

Используйте RemoteTaskRunner для загрузки плагина во вторичном appDomain:

RemoteTaskRunner taskRunner = m_domain.CreateInstanceAndUnwrap(
                    Assembly.GetExecutingAssembly().FullName,
                    typeof (RemoteTaskRunner).FullName) as RemoteTaskRunner;
taskRunner.LoadTask(taskInfo.Assembly, taskInfo.Type);

Используйте RemoteTaskRunner для Выполнения задачи во вторичном appDomain:

[Serializable]
internal class RemoteTaskRunner : MarshalByRefObject
{
    private ITask m_task;

    public RemoteTaskRunner()
    {
    }

    internal void LoadTask(string assembly, string type)
    {
        // This assembly should load in the secondary appDomain.
        Assembly taskAssembly = AppDomain.CurrentDomain.Load(assembly);
        m_task = taskAssembly.CreateInstance(type) as ITask;
    }

    internal void RunTask(string taskConfig)
    {
        // This method should run in the secondary appDomain.
        m_task.RunTask(taskConfig, m_logger);
    }
...
...

Для выполнения сменной задачи следующая строка кода используется в Основном appDomain:

taskRunner.RunTask(taskInfo.TaskConfig);

После концов задачи разгружен appDomain:

AppDomain.Unload(m_domain);
0
ответ дан 10 December 2019 в 00:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: