Утечка памяти в EmulationTrader + LocalMarketDataDrive


Утечка памяти в EmulationTrader + LocalMarketDataDrive
Atom
15.10.2013


Гоняю 1000 итераций, где в каждой создаю EmulationTrader и все необходимое, он отрабатывает, уничтожаю объекты. Память накапливается, и программа заканчивается с OutOfMemory Exception.
Вызываю для всех объектов где надо Dispose(), где надо null, отписываюсь от событий, но память все равно течет.

Профайлером ANTS Memory Profiler я увидел, что продолжают висеть в памяти EmulationTrader-ы и LocalMarketDateDrive-ы. На них ссылаются делегаты (видимо, их же обработчики, подписавшиеся на события извне). Вот последовательность взаимных ссылок, которые держат объекты (читать лучше снизу вверх: удерживаемый объект - внизу, корневая удерживающая ссылка - вверху):

1. Делегат LocalMarketDataDrive-а
Код
static LazyHelpers _delegates (references to ->)
   Ecng.Collections.SyncrhonizedDictionary<Object, Delegate> _inner ->
     Dictionary<Object, Delegate>  entries ->
       it's [0].Value  ->
         (delegate) System.Func<CachedSyncronizedOrderDictionary<DateTime, DateTime>> (inside LocalMarketDataDrive) ->
           LocalMarketDataDrive


2. Делегат EmulationTrader-а
Код
 static List<Ecng.ComponentModel.EventsContainer> _containers ->
   it's _items[0] -> 
     EventsContainer<Security> _processDataError ->
       (delegate) System.Action<Exception> (inside EmulationTrader) ->
         EmulationTrader (internal field #=q.....GZQ==)->
           LocalMarketDataDrive 


Поскольку у меня нет исходников S#, то догадки свои проверить не могу. Могу прислать дампы программы для анализа. Ну, и привести кусочки кода создания/освобождения объектов.
Буду очень благодарен за исправления!

UPD. Версия последняя, 4.1.19.1



Спасибо: Bond Mikhail Sukhov


< 1 2 
pafnuty

Фотография
Дата: 20.10.2013
Ответить


Михаил Сухов Перейти
Спасибо за фидбэк. А возможно ли сделать некий мини код (желательно с теми маркет-данными, что идут в нашем дистрибутиве), который бы демонстрировал утечку на итерациях?

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


1. Вот тестовый проект: http://yadi.sk/d/omfHs1P0BFfZq

Не очень мини получилось - я просто выцепил кусок своей программы, выкинул все ненужное. Стратегию взял из SampleHistoryTesting, но переделал ее на свой лад, как я работал с тиками (чтобы можно было увидеть мои утечки, а заодно и средства борьбы с ними). Я думаю, что можно также прозрачно подставить туда и исходную SmaStrategy, только переопределить в ней Clone() и добавить конструктор по умолчанию. Ну, и CandleManager подцепить, сейчас я работал без него.

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

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


2. Попутно я боролся с утечками. После тех брутальных Clear() я смог еще кое-что обнаружить и убить (наверное, неаккуратно). Удалось сбросить до ~60Мб на 1000 итераций.

  • Течет немножко MarketEmulator. Сделал ему Dispose(). После Dispose() все равно какие-то ссылки на SyncrhonizedList<Order>, SyncrhonizedDictionary<MyTrade>, Dictionary<Security, MarketEmulator+#какая-то хрень#>, там же где-то MarketDepth и с ним Quote[]. Где они там, и как их победить, я не разобрался.

  • У EmulationTrader после Dispose() тоже что-то висит: SyncrhonizedDictionary<MyTrade>, BlockingQueue<Message>, SyncrhonizedDictionary<Order, SyncrhonizedList<MyTrade> >. От него остался висеть BaseTrader, в котором висят CachedSynchronizedList<MyTrade>. И т.д.

  • Есть еще какие-то два static SyncrhonizedDictionary<Order, #какая-то хрень#>, в которых накапливаются Order и DateTime, у которых в свою очередь _trader держит уже отDisposeнный EmulationTrader.

Возможно, брутальные Clear() что-то неаккуратно чистят. Я не пробовал разные схемы.
Спасибо: Bond

pafnuty

Фотография
Дата: 28.10.2013
Ответить


Обнаружил тут, что в своем исходнике я 2 раза подписывался/отписывался на стаканы для одного и того же Security (в обоих случаях один и тот же объект - клон):

  • в OptimizerTest.CreateTrader()/ReleaseTrader()
  • и в MarketDephtSmaStrategy.OnStarted()/OnStopping()


Возможно, это тоже приводит к утечке (хотя, я так не думаю).
Спасибо:
< 1 2 

Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy