Я создал небольшую службу Windows, которая запускает плагины.
Каждый плагин - это dll, который загружается в отдельный AppDomain
с использованием метода CreateInstanceAndUnwrap
, и я сохраняю ссылку на AppDomain
.
Как только плагин завершает работу, я выключаю AppDomain
, созданный для этого плагина. Я использую теневое копирование, чтобы разрешить обновления плагинов, пока они работают в платформе.
Он работал в течение 6 месяцев до последней недели, когда я решил поместить основные функциональные возможности фреймворка также в отдельную DLL и выполнить эту DLL в отдельном AppDomain
.
Как это работает прямо сейчас:
- Служба Windows запускается.
- Ядро ядра загружается и выполняется с использованием
CreateInstanceAndUnwrap
, которое, в свою очередь, отвечает за запуск плагинов в их отдельных AppDomain
У меня есть несколько разных мест для сборок:
- Папка с корзиной (в корзине Windows хранятся только библиотеки DLL, используемые этой службой)
- Core DLLs Folder (здесь находятся основные библиотеки DLL)
- Папка со ссылками (любые ссылки здесь)
- Папка плагинов (здесь плагины)
Я разрешаю любые необнаруженные dll, подключаясь к каждому событию OnAssemblyResolve
на AppDomain
. Это позволяет загружать dll из сети.
Теперь проблема в том, что служба Windows работала в течение одного дня, а память поднялась до 1,5 ГБ. Я создал дамп памяти и похоже, что загруженные модули занимают всего 100 МБ из 1,5 ГБ, поэтому я не знаю, куда уходит вся эта память.
Используя отладку, я увидел предупреждение о фрагментации кучи, но понятия не имею, с чего начать диагностику проблемы. Обычно, когда фреймворк работает в течение дня, он потребляет что-то вроде 100M.
Также это не относится к плагинам; когда я откатил свои изменения в фреймворке, использование памяти стало нормальным, как и раньше. Когда я создаю AppDomain
для плагинов, я переключаю basePath и путь к корзине AppDomain
на папки CORE и References, в которых находится большинство dll, в надежде, что разрешение сборки вызывается реже.
Я посмотрел журналы Fusion, а также прочитал немного больше о контекстах загрузки, таких как default, from и ничего, но я не уверен, что это правильный путь.
Есть идеи?