кто получает больше прибыли от объединения?управляемый / неуправляемый? - PullRequest
1 голос
/ 17 января 2011

Наличие двух одинаковых приложений: одно управляемое, а другое неуправляемое. Оба используют тяжелый шаблон распределения для больших объектов. То есть они запрашивают множество этих объектов в цикле (длительном запуске) и оба сразу же освобождают эти объекты после использования. Управляемое приложение использует IDisposable (), который вызывается немедленно. Неуправляемый использует деструкторы.

Некоторые, но не все объекты могут быть использованы повторно. Итак, пул рассматривается для увеличения скорости выполнения и минимизации риска фрагментации памяти.

Какое приложение вы ожидаете получить больше прибыли от объединения и почему?

@ Обновление: речь идет о математической библиотеке. Следовательно, эти большие объекты будут массивами типа значения. В основном достаточно большой для LOH. Я уверен, что объединение улучшит производительность на управляемой стороне. Существует много библиотек - для управляемых / неуправляемых сред. Никто из них, которых я знаю, не делает такое объединение действительно. Мне интересно почему?

Ответы [ 2 ]

3 голосов
/ 17 января 2011

Сначала немного рассмотрим, что такое большой объект. В .net считается, что большой объект имеет 85 000 или более байтов. У вас действительно есть такие большие объекты или у вас очень большой график из более мелких объектов?

Если это график более мелких объектов, то они хранятся в SOH (куче небольших объектов). В этом случае, если вы создаете объекты и отпускаете их немедленно, вы получите максимальную выгоду от оптимизаций сборщика мусора, предполагающих модель поколений. Я имею в виду, что вы либо создаете объекты и позволяете им умирать, либо сохраняете их навсегда. Держать их просто «на некоторое время», или, другими словами, объединение, просто позволит им продвинуться до более высоких поколений (до 2-го поколения), и это снизит производительность GC, потому что очистка объектов 2-го поколения стоит дорого ( вечные объекты во втором поколении не дорогие, однако). Не беспокойтесь о фрагментации памяти. Если вы не выполняете взаимодействие или такие сложные вещи, как закрепление объектов, GC очень эффективен для предотвращения фрагментации памяти - он сжимает память, освобождая ее от эфемерного сегмента.

Если у вас действительно есть очень большие объекты (например, очень большие массивы), то он может заплатить, чтобы объединить их. Однако обратите внимание, что если массивы содержат ссылки на меньшие объекты, их объединение приведет к проблемам, о которых я говорил в предыдущем абзаце, поэтому вам следует тщательно очищать массив (его ссылки указывают на ноль) часто (каждую итерацию? ).

С учетом вышесказанного тот факт, что вы вызываете IDisposable, не является очисткой объектов. GC делает так. Утилизация отвечает за очистку неуправляемых ресурсов. Тем не менее, очень важно, чтобы вы продолжали вызывать Dispose для каждого объекта, класс которого реализует IDisposable (лучший способ - наконец-то), потому что вы потенциально освобождаете неуправляемые ресурсы немедленно, а также потому, что вы говорите GC, что это не нужно вызывать финализатор объекта, что привело бы к ненужному продвижению объекта, что, как мы видели, является нет нет.

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

Чтобы действительно понять, о чем я говорю:

Сборка мусора: автоматическое управление памятью в Microsoft .NET Framework

Сборка мусора: автоматическое управление памятью в Microsoft .NET Framework 2

Обнаружена куча больших объектов

1 голос
/ 17 января 2011

Странно, но я постараюсь ответить сам. Могу ли я получить некоторые комментарии к этому:

Обе платформы страдают от фрагментации, если очень большие объекты выделяются и освобождаются интенсивным образом (циклы). В случае неуправляемых приложений выделения производятся непосредственно из виртуального адресного пространства. Обычно рабочий массив будет заключен в класс (c ++), обеспечивающий перегрузки операторов для приятного короткого синтаксиса, некоторую обработку ссылок и деструктор, который гарантирует, что массив освобождается немедленно при выходе из области видимости. Тем не менее, запрошенные массивы не всегда имеют один и тот же размер - если запрашиваются большие массивы, один и тот же адресный блок не может быть повторно использован, что может привести к фрагментации с течением времени. Кроме того, нет способа найти блок , который точно соответствует запрашиваемой длине массива. Операционная система просто использовала бы первый блок, который достаточно велик - даже если бы он был больше по мере необходимости и, возможно, мог бы лучше выполнить запрос для последующего предстоящего еще большего массива. Как объединение может улучшить эту ситуацию?

Вообразимым было бы использование больших массивов для небольших запросов. Класс будет обрабатывать переход от истинной длины базового массива к виртуальной длине, необходимой для внешнего мира. Пул может помочь доставить «первый массив, который достаточно длинный» - в отличие от ОС, которая всегда будет давать точную длину. Это может ограничить фрагментацию, поскольку в виртуальном адресном пространстве создается меньше дыр. С другой стороны, общий объем памяти увеличится. Для почти случайных паттернов распределения пул почти ничего не даст, а, скорее всего, потребляет только редкую память.

На управляемой стороне ситуация хуже. Прежде всего, существуют две возможные цели фрагментации: виртуальное адресное пространство и управляемая куча больших объектов. Последним в этом случае будет набор отдельных сегментов, индивидуально выделенных из ОС. Каждый сегмент будет в основном использоваться только для одного массива (так как здесь мы говорим о действительно больших массивах). Если GC освобождает один массив, весь сегмент возвращается в ОС. Так что фрагментация не будет проблемой в LOH (ссылки: мои собственные мысли и некоторые эмпирические наблюдения с использованием VMMap, поэтому любые комментарии очень приветствуются!).

Но поскольку сегменты LOH выделяются из виртуального адресного пространства, здесь также возникает проблема фрагментации - как и для неуправляемых приложений. Фактически, схема распределения для обоих приложений должна выглядеть очень похожей для менеджера памяти ОС. (?) С одним отличием: массивы освобождаются GC одновременно. Тем не менее, «действительно большие массивы» будут оказывать большое давление на сборщик мусора. Только относительно небольшое количество «действительно больших массивов» может храниться одновременно, пока не произойдет сбор. По сути, приложение обычно тратит разумное количество времени (около 5,45%) в GC, также потому, что практически все коллекции будут дорогими коллекциями Gen2, и почти каждое выделение приведет к такой коллекции Gen 2.

Здесь объединение может значительно помочь. Как только массивы не освобождаются в ОС, а собираются в пул, они немедленно доступны для дальнейших запросов. (Это одна из причин, почему IDisposable предназначен не только для неуправляемых ресурсов). Фреймворк / библиотека должны только убедиться, что массивы размещены в пуле достаточно рано и позволяют повторно использовать большие массивы в ситуациях, когда на самом деле требуется меньший размер.

...