Вызовите сборку "мусора" массивов, C#

Маленькие статические изображения (не больше чем несколько megs), которые не часто редактируются, должны быть сохранены в базе данных. Этот метод обладает несколькими преимуществами включая более легкую мобильность (изображения передаются с базой данных), более легкое резервное копирование/восстановление (изображения сохранены с базой данных), и лучшая масштабируемость (папка файловой системы с тысячами небольших файлов миниатюры походит на кошмар масштабируемости мне).

Подающие изображения от базы данных легки, просто реализуйте http обработчик, который служит массиву байтов, возвращенному из сервера БД как двоичный поток.

17
задан John Doe 10 July 2009 в 21:05
поделиться

10 ответов

Это не точный ответ на исходный вопрос: «как заставить сборку мусора», но, тем не менее, Я думаю, это поможет вам еще раз изучить вашу проблему.

После просмотра вашего комментария

  • Помещение GC.Collect (); действительно помогает, хотя это все еще не решает проблему полностью - по какой-то причине программа все еще вылетает, когда выделяется около 1,3 ГБ (я использую System.GC.GetTotalMemory (false); чтобы найти реальную выделенную сумму).

Я подозреваю, что у вас может быть фрагментация памяти . Если объект большой (85000 байт в среде CLR .net 2.0, если я правильно помню, я не знаю, был ли он изменен или нет), объект будет размещен в специальной куче, Куча больших объектов (LOH) . GC действительно освобождает память, используемую недоступными объектами в LOH, но он не выполняет уплотнение в LOH, как это происходит с другими кучами (gen0, gen1 и gen2) из-за производительности.

Если вы часто выделяете и освобождаете большие объекты, это сделает LOH фрагментированным, и даже если у вас в общей сложности больше свободной памяти, чем вам нужно, у вас может больше не быть непрерывного пространства памяти, следовательно, вы получите исключение OutOfMemory.

На данный момент я могу придумать два обходных пути.

  1. Перейдите на 64-битную машину / ОС и воспользуйтесь этим :) (Самый простой, но, возможно, и самый сложный, в зависимости от ваших ограничений ресурсов)
  2. Если вы не можете сделать №1, попробуйте выделить огромную часть сначала используйте память и используйте их (может потребоваться написать некоторый вспомогательный класс для управления меньшим массивом, который на самом деле находится в большем массиве), чтобы избежать фрагментации. Это может немного помочь, но не может полностью решить проблему, и вам, возможно, придется столкнуться со сложностью.
15
ответ дан 30 November 2019 в 11:32
поделиться

Не это просто фрагментация кучи больших объектов? Объекты размером> 85 000 байт размещаются в куче больших объектов. Сборщик мусора освобождает место в этой куче, но никогда не сжимает оставшиеся объекты. Это может привести к нехватке непрерывной памяти для успешного выделения большого объекта.

Alan.

4
ответ дан 30 November 2019 в 11:32
поделиться

Похоже, вы столкнулись с проблемой фрагментации LOH (кучи больших объектов).

Куча больших объектов

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

Вы можете проверить, есть ли у вас возникают проблемы с фрагментацией loh при использовании SOS

Посмотрите этот вопрос , чтобы увидеть, как использовать SOS для проверки loh.

9
ответ дан 30 November 2019 в 11:32
поделиться

Если бы мне пришлось предположить, что проблема не в том, что вы переходите с Vector3 [200,200,200] на Vector3 [210,210,210], а в том, что, скорее всего, у вас были аналогичные предыдущие шаги перед этим:

 i.e.   
    // first you have
    Vector3[10,10,10];
    // then
    Vector3[20,20,20];
    // then maybe
    Vector3[30,30,30];
    //  .. and so on ..
    //  ...
    // then
    Vector3[200,200,200];
    // and eventually you try
    Vector3[210,210,210] // and you get an OutOfMemoryException..

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

Итак, вместо приведенного выше, используйте что-то вроде этого:

 // first start with an arbitrary size
 Vector3[64,64,64];
 // then double that
 Vector3[128,128,128];
 // and then.. so in thee steps you go to where otherwise 
 // it would have taken you 20..
 Vector3[256,256,256];
2
ответ дан 30 November 2019 в 11:32
поделиться

Они могут не собираться, потому что они ' вас ссылаются на то, чего вы не ожидаете.

В качестве теста попробуйте вместо этого изменить свои ссылки на WeakReferences и посмотрите, решит ли это вашу проблему с OOM. Если нет, то вы ссылаетесь на них в другом месте.

1
ответ дан 30 November 2019 в 11:32
поделиться

Исключение OutOfMemory внутренне запускает цикл GC автоматически один раз и пытается выделить снова, прежде чем фактически выбросить исключение в ваш код. Единственный способ получить исключения OutOfMemory - это если вы храните ссылки на слишком большой объем памяти. Удалите ссылки, как только сможете, присвоив им null.

0
ответ дан 30 November 2019 в 11:32
поделиться

Частично проблема может заключаться в том, что вы выделяете многомерный массив, который представлен в виде одного непрерывного блока памяти в куче больших объектов (подробнее здесь ) ). Это может заблокировать другие выделения, поскольку нет свободного непрерывного блока для использования, даже если где-то еще есть свободное место, отсюда OOM.

Попробуйте выделить его как зубчатый массив - Vector3 [210] [210] [ 210] - который распределяет массивы по памяти, а не как один блок, и посмотрите, улучшит ли это положение

0
ответ дан 30 November 2019 в 11:32
поделиться

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

Это сказал, если вы хотите эту функциональность, почему бы не создать ее?

public static void Collect(ref object o)
{
    o = null;
    GC.Collect();
}
1
ответ дан 30 November 2019 в 11:32
поделиться

Джон, Создание объектов размером> 85000 байт приведет к тому, что объект окажется в куче больших объектов. Куча больших объектов никогда не сжимается, вместо этого снова используется свободное пространство. Это означает, что если вы каждый раз выделяете более крупные массивы, вы можете оказаться в ситуациях, когда LOH фрагментирован, отсюда и OOM.

вы можете проверить, что это так, прервав работу отладчика в точке OOM и получив сообщение dump, отправив этот дамп в MS через ошибку подключения ( http://connect.microsoft.com ), было бы отличным началом.

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

Я не знаю, какова политика совместного использования дампов памяти в Stackoverflow, но я бы с удовольствием посмотрю, чтобы лучше понять вашу проблему.

0
ответ дан 30 November 2019 в 11:32
поделиться

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

array1 = null;
GC.Collect();
array1 = new Vector3[210,210,210];
7
ответ дан 30 November 2019 в 11:32
поделиться
Другие вопросы по тегам:

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