У меня есть синтаксический анализ данных. Я работаю над явным размером текстовых файлов, которые он читает, и управление памятью является ключевым для хорошей производительности. Стратегия двух частей здесь сначала измеряет, сколько ОЗУ каждого файла будет способствовать сумме, но также необходимо знать, сколько оперативной памяти доступно для приложения в данный момент времени. Если доступно достаточное количество ОЗУ, приложение предпочитает выполнять свою обработку в памяти. В противном случае он переключается на режим, который выполняет все или большинство операций на диске.Измерьте общий объем оперативной памяти, доступной для приложения
Измерение взноса файла на использование памяти быстро и легко:
static Int64 GetSizeInMemory(string path)
{
//THIS CODE IS SPEEDY
Int64 r = ((Func<Int64>)(
() =>
{
try
{
using (Stream s = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(s, File.ReadAllLines(path));
return s.Length;
}
}
catch
{
//this file is way too big
return -1;
}
}
))();
GC.Collect();
GC.WaitForPendingFinalizers();
return r;
}
Однако измерения общего объема памяти, доступной является медленным и трудным. В этом случае я попытался сделать это, захватив ошибку переполнения стека, которая, по моему мнению, должна дать самую надежную цифру.
static Int64 GetMaxAllowedMemory()
{
//THIS CODE IS SLOW
Int64 r = ((Func<Int64>)(
() =>
{
byte[] b = new byte[]{};
Int64 rs = 0;
while (true)
{
try
{
Array.Resize<byte>(ref b, b.Length + 1);
b[b.Length - 1] = new byte();
rs = b.Length;
} catch (Exception e) {
break;
}
}
b = null;
return rs;
}
))();
GC.Collect();
GC.WaitForPendingFinalizers();
return r;
}
Есть ли лучший подход, который я должен использовать здесь?
Обращаем внимание,. Я рассмотрел ряд вопросов, подобных этому при переполнении стека, но большинство имеет дело только с получением фигуры для общего объема доступной ОЗУ на компьютере, что не совпадает с Максимальный объем оперативной памяти во время выполнения разрешен для .NET-процесса.
UPDATE
После получения ответа, я придумал следующее, что позволяет мне, чтобы получить общее количество оперативной памяти, доступной для применения.
static Int64 GetMemoryFailPoint()
{
Int64 r = ((Func<Int64>)(
() =>
{
int rs = 1;
while (true)
{
try
{
using (new System.Runtime.MemoryFailPoint(rs))
{
}
}
catch {
break;
}
rs++;
}
return Convert.ToInt64(rs) * 1000000;
}
))();
return r;
}
Для вашего обновления вы, скорее всего, можете сделать свой код намного быстрее, увеличив его, удвоив значение до тех пор, пока оно не сработает, а затем разделите его на 2 и медленно продвигайтесь после этой точки. Кроме того, в [разделе замечаний документации] (https://msdn.microsoft.com/en-us/library/system.runtime.memoryfailpoint (v = vs.110) .aspx) * «MemoryFailPoint работает с детализацией из 16 МБ. Любые значения меньше 16 МБ обрабатываются как 16 МБ, а другие значения рассматриваются как следующий по величине кратный 16 МБ "*, поэтому' rs ++ 'должен быть' rs + = 16', вы делаете 15 дополнительных проверок который вернет тот же результат. –
Наконец, в MB есть '1 << 20' (' 1048576') байт, поэтому ваш возврат должен быть 'return Convert.ToInt64 (rs) * (1 << 20);'. Для 2048 МБ (2 ГБ) это будет разница в 99 483 648 байтов. –
@ScottChamberlain Спасибо! Я обязательно это рассмотрю. Кроме того, указатель о возврате наиболее полезен. –