Можно ли изменить коллекцию ReadOnlyCollection с помощью отражения - PullRequest
1 голос
/ 08 марта 2011

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

Чтобы сделать то, что мне нужно, я должен перебрать тысячи этих объектов (почти 100 000), и, хотя я определенно не сохраняю ссылки на эти объекты, объектная модель в SDK, который я использую, делает. Это пережевывает память и опасно близко к возникновению OutOfMemoryExceptions.

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

foreach (Build build in builds)
{
        BinaryFileCollection numBinaries = build.GetBinaries();
        foreach (BinaryFile binary in numBinaries)
        {
            this.CoveredBlocks += binary.HitBlockCount;
            this.TotalBlocks += binary.BlockCount;
            this.CoveredArcs += binary.HitArcCount;
            this.TotalArcs += binary.ArcCount;

            if (binary.HitBlockCount > 0)
            {
                this.CoveredSourceFiles++;
            }

            this.TotalSourceFiles++;

            foreach (Class coverageClass in binary.GetClasses())
            {
                if (coverageClass.HitBlockCount > 0)
                {
                    this.CoveredClasses++;
                }

                this.TotalClasses++;

                foreach (Function function in coverageClass.GetFunctions())
                {
                    if (function.HitBlockCount > 0)
                    {
                        this.CoveredFunctions++;
                    }

                    this.TotalFunctions++;
                }
            }

            FieldInfo fi = typeof(BinaryFile).GetField("classes", BindingFlags.NonPublic | BindingFlags.Instance);
            fi.SetValue(binary, null);
    }

Когда я проверяю значения члена класса в numBinaries [0], он возвращает ноль, что выглядит как выполненная миссия, но когда я запускаю этот код, потребление памяти просто растет и растет, так же быстро, как когда я не устанавливайте классы на ноль вообще.

Что я пытаюсь выяснить, так это то, что в этом подходе есть недостатки или есть другой объект, хранящий ссылки на классы ReadOnlyCollection, которые мне не хватает.

1 Ответ

0 голосов
/ 09 марта 2011

Я могу придумать несколько альтернатив ...

  1. Логически разделить это. Вы упомянули, что он сохраняет все ссылки «на время соединения». Можете ли вы сделать 10%, закрыть его, открыть новый, пропустить эти 10%, взять еще 10% (всего 20%) и т. Д.?
  2. Сколько памяти мы говорим здесь, и будет ли этот инструмент долговечным? Так что, если он использует много оперативной памяти в течение нескольких минут? Вы на самом деле получаете ООМ? Если в вашей системе достаточно свободной оперативной памяти для программы, почему бы не использовать ее? Вы заплатили за оперативную память. Это напоминает мне одно из сообщений в блоге Раймона Чена о 100% потреблении процессора.
  3. Если вы действительно хотите увидеть, что мешает что-то собирать мусор, запустите SOS и используйте !gcroot - это место для начала.

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

...