Маленькие статические изображения (не больше чем несколько megs), которые не часто редактируются, должны быть сохранены в базе данных. Этот метод обладает несколькими преимуществами включая более легкую мобильность (изображения передаются с базой данных), более легкое резервное копирование/восстановление (изображения сохранены с базой данных), и лучшая масштабируемость (папка файловой системы с тысячами небольших файлов миниатюры походит на кошмар масштабируемости мне).
Подающие изображения от базы данных легки, просто реализуйте http обработчик, который служит массиву байтов, возвращенному из сервера БД как двоичный поток.
Это не точный ответ на исходный вопрос: «как заставить сборку мусора», но, тем не менее, Я думаю, это поможет вам еще раз изучить вашу проблему.
После просмотра вашего комментария
Я подозреваю, что у вас может быть фрагментация памяти . Если объект большой (85000 байт в среде CLR .net 2.0, если я правильно помню, я не знаю, был ли он изменен или нет), объект будет размещен в специальной куче, Куча больших объектов (LOH) . GC действительно освобождает память, используемую недоступными объектами в LOH, но он не выполняет уплотнение в LOH, как это происходит с другими кучами (gen0, gen1 и gen2) из-за производительности.
Если вы часто выделяете и освобождаете большие объекты, это сделает LOH фрагментированным, и даже если у вас в общей сложности больше свободной памяти, чем вам нужно, у вас может больше не быть непрерывного пространства памяти, следовательно, вы получите исключение OutOfMemory.
На данный момент я могу придумать два обходных пути.
Не это просто фрагментация кучи больших объектов? Объекты размером> 85 000 байт размещаются в куче больших объектов. Сборщик мусора освобождает место в этой куче, но никогда не сжимает оставшиеся объекты. Это может привести к нехватке непрерывной памяти для успешного выделения большого объекта.
Alan.
Похоже, вы столкнулись с проблемой фрагментации LOH (кучи больших объектов).
CLR Наизнанку кучи больших объектов не обнаружена
Вы можете проверить, есть ли у вас возникают проблемы с фрагментацией loh при использовании SOS
Посмотрите этот вопрос , чтобы увидеть, как использовать SOS для проверки loh.
Если бы мне пришлось предположить, что проблема не в том, что вы переходите с 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];
Они могут не собираться, потому что они ' вас ссылаются на то, чего вы не ожидаете.
В качестве теста попробуйте вместо этого изменить свои ссылки на WeakReferences и посмотрите, решит ли это вашу проблему с OOM. Если нет, то вы ссылаетесь на них в другом месте.
Исключение OutOfMemory внутренне запускает цикл GC автоматически один раз и пытается выделить снова, прежде чем фактически выбросить исключение в ваш код. Единственный способ получить исключения OutOfMemory - это если вы храните ссылки на слишком большой объем памяти. Удалите ссылки, как только сможете, присвоив им null.
Частично проблема может заключаться в том, что вы выделяете многомерный массив, который представлен в виде одного непрерывного блока памяти в куче больших объектов (подробнее здесь ) ). Это может заблокировать другие выделения, поскольку нет свободного непрерывного блока для использования, даже если где-то еще есть свободное место, отсюда OOM.
Попробуйте выделить его как зубчатый массив - Vector3 [210] [210] [ 210] - который распределяет массивы по памяти, а не как один блок, и посмотрите, улучшит ли это положение
Я понимаю, что вы пытаетесь сделать, и настаивать на немедленной сборке мусора, вероятно, неправильный подход (поскольку сборщик мусора по-своему тонкий и быстро вызывает гнев).
Это сказал, если вы хотите эту функциональность, почему бы не создать ее?
public static void Collect(ref object o)
{
o = null;
GC.Collect();
}
Джон, Создание объектов размером> 85000 байт приведет к тому, что объект окажется в куче больших объектов. Куча больших объектов никогда не сжимается, вместо этого снова используется свободное пространство. Это означает, что если вы каждый раз выделяете более крупные массивы, вы можете оказаться в ситуациях, когда LOH фрагментирован, отсюда и OOM.
вы можете проверить, что это так, прервав работу отладчика в точке OOM и получив сообщение dump, отправив этот дамп в MS через ошибку подключения ( http://connect.microsoft.com ), было бы отличным началом.
Я могу вас заверить, что GC сделает все правильно то, что пытается удовлетворить ваш запрос на выделение, это включает запуск сборщика мусора для очистки старого мусора для удовлетворения новых запросов на выделение.
Я не знаю, какова политика совместного использования дампов памяти в Stackoverflow, но я бы с удовольствием посмотрю, чтобы лучше понять вашу проблему.
Принудительная сборка мусора не всегда является хорошей идеей (в некоторых ситуациях она действительно может увеличить время жизни объектов). Если нужно, используйте:
array1 = null;
GC.Collect();
array1 = new Vector3[210,210,210];