Автор Тема: Утечка виртуальной памяти  (Прочитано 8736 раз)

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Утечка виртуальной памяти
« : Март 16, 2012, 07:54:12 pm »
Неожиданно столкнулся со следующей проблемой. Вот уже во второй раз (сегодня был один случай, и вчера) программа (под Mono 2.6.7) выжрала всю виртуальную память (3 ГБ) и при попытке выделить память под массив на 5 Мб кидает исключение OutOfMemory. Физической памяти занято сущие копейки -- всего 130 Мб. Под Виндос не воспроизводится. Что за напасть такая... Как бороться с утечками виртуальной памяти?

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

Кстати вопрос к знатокам Линукса: какую API функцию надо звать чтоб узнать количество занятой памяти? Читать псевдокаталог proc не хочу, должна же быть нормальная API функция.

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #1 : Март 16, 2012, 08:09:28 pm »
man getrusage
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #2 : Март 16, 2012, 08:12:19 pm »
Насколько я понимаю, идет утечна "адресного пространства". Ведь своп же не растет, так?
Быть может у вас там где-то mmap'ится что-то без последующего munmap?
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Romiras

  • Sr. Member
  • ****
  • Сообщений: 264
    • Просмотр профиля
    • Romiras Dev Lab
Re: Утечка виртуальной памяти
« Ответ #3 : Март 17, 2012, 11:20:34 am »
Вчера искал...
#include <unistd.h>

long getTotalSystemMemory()
{
    long pages = sysconf(_SC_PHYS_PAGES);
    long page_size = sysconf(_SC_PAGE_SIZE);
    return pages * page_size;
}
При условии, что из Моно можно вызывать C функции.

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Утечка виртуальной памяти
« Ответ #4 : Март 19, 2012, 05:43:27 am »
man getrusage
Это оказалось не то, что нужно. В поле getrusage.ru_maxrss пишется реальная память, а мне нужна виртуальная.

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Утечка виртуальной памяти
« Ответ #5 : Март 19, 2012, 11:12:37 am »
Несколько часов гугления результата не дали. Так и пришлось читать псевдофайл "/proc/self/status", искать в нём строку начинающуюся на "VmSize:" и парсить её. Не ожидал я такой подставы от Линукса. Вот это да. Позор разработчикам линуксового API!!!

Romiras

  • Sr. Member
  • ****
  • Сообщений: 264
    • Просмотр профиля
    • Romiras Dev Lab
Re: Утечка виртуальной памяти
« Ответ #6 : Март 19, 2012, 11:55:50 am »
Несколько часов гугления результата не дали. Так и пришлось читать псевдофайл "/proc/self/status", искать в нём строку начинающуюся на "VmSize:" и парсить её. Не ожидал я такой подставы от Линукса. Вот это да. Позор разработчикам линуксового API!!!
И чего тут удивляться - типичный дистрибутив Линукса не обходится без Перла.   ;)

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #7 : Март 19, 2012, 02:27:21 pm »
Несколько часов гугления результата не дали. Так и пришлось читать псевдофайл "/proc/self/status", искать в нём строку начинающуюся на "VmSize:" и парсить её. Не ожидал я такой подставы от Линукса. Вот это да. Позор разработчикам линуксового API!!!

Я так понимаю (после тесного знакомства c OSX) - это вполне нормальная ситуация в юникс системах. Не парься :) Сам прибегал к подобным решениям неоднократно. Проблемы тоже понятно какие - выходит новая версия с другим форматированием...

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #8 : Март 19, 2012, 05:27:29 pm »
Посмотрел исходники top и atop - таки они под линуксом реально парсят /proc/pid/stat. К сожалению этот способ не описан в ISO-стандарте LSB (Linux standard base), не говоря уже о SUS (Single unix specification). Соответственно это действительно может измениться (как впрочем и любой API который туда не входит. То есть нет разницы в плане надежности и неизменности API это или же какой-то псевдофайл текстовый. Причем не стандартизированное API обычно меняется более резво чем текстовое файло, ибо затрагивает только программистов, а файло еще и сисадминов-скриптовиков).

Собственно дока по этому делу тут: http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html Там же сказано и в какой исходник смотреть на предмет изменения.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #9 : Март 19, 2012, 05:29:11 pm »
Несколько часов гугления результата не дали. Так и пришлось читать псевдофайл "/proc/self/status", искать в нём строку начинающуюся на "VmSize:" и парсить её. Не ожидал я такой подставы от Линукса. Вот это да. Позор разработчикам линуксового API!!!

Я так понимаю (после тесного знакомства c OSX) - это вполне нормальная ситуация в юникс системах. Не парься :) Сам прибегал к подобным решениям неоднократно.
Ну, ты таки немного лукавишь - бОльшая часть геморроев с OSX у тебя как раз из за необходимости поддерживать древнюю версию которая как раз еще не Unix. А вот начиная с Unix-версии, все стало существенно лучше. :-)
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #10 : Март 19, 2012, 05:34:17 pm »
Посмотрел исходники top и atop - таки они под линуксом реально парсят /proc/pid/stat. К сожалению этот способ не описан в ISO-стандарте LSB (Linux standard base), не говоря уже о SUS (Single unix specification). Соответственно это действительно может измениться (как впрочем и любой API который туда не входит. То есть нет разницы в плане надежности и неизменности API это или же какой-то псевдофайл текстовый

Таки ты тоже  немного лукавишь ;) В случае API - сломается компиляция, в отличие от ;)

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #11 : Март 19, 2012, 05:35:58 pm »
Кстати, сама /proc в линуксе слизана с Plan9, которая, в свою очередь, расширила и углубила идею /proc из Unix v8 (1984 год: http://man.cat-v.org/unix_8th/4/proc ).
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Утечка виртуальной памяти
« Ответ #12 : Март 19, 2012, 05:40:01 pm »
Посмотрел исходники top и atop - таки они под линуксом реально парсят /proc/pid/stat. К сожалению этот способ не описан в ISO-стандарте LSB (Linux standard base), не говоря уже о SUS (Single unix specification). Соответственно это действительно может измениться (как впрочем и любой API который туда не входит. То есть нет разницы в плане надежности и неизменности API это или же какой-то псевдофайл текстовый

Таки ты тоже  немного лукавишь ;) В случае API - сломается компиляция, в отличие от ;)
Это не обязательно. В некоторых случаях компиляция может и не сломаться :-) Тем более что уже скомпиленное в случае изменения API схлопочет сегфолт (в лучшем случае).

В случае текстового файла скрипты тоже сломаются, если например число параметров станет другим, или их формат поменяется. Хотя может и не сломаться, а начать просто выводить чушь, что ЕЩЕ ХУЖЕ.

;-)
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Утечка виртуальной памяти
« Ответ #13 : Март 20, 2012, 07:58:01 am »
Немножко исходников

      private static class Linux
      {
        public static void GetMemorySize (out long virtualSize, out long residentSize)
        {
          const string VmSize = "VmSize:";
          const string VmRSS = "VmRSS:";
          virtualSize = 0;
          residentSize = 0;
          using (System.IO.StreamReader rd = System.IO.File.OpenText("/proc/self/status"))
          {
            while (!rd.EndOfStream && ((virtualSize == 0) || (residentSize == 0)))
            {
              string line = rd.ReadLine();
              if (line.StartsWith(VmSize))
              {
                string s = line.Substring(VmSize.Length, line.Length - VmSize.Length - 3);
                long x;
                long.TryParse(s, out x);
                virtualSize = x * 1024;
              }
              else if (line.StartsWith(VmRSS))
              {
                string s = line.Substring(VmRSS.Length, line.Length - VmRSS.Length - 3);
                long x;
                long.TryParse(s, out x);
                residentSize = x * 1024;
              }
            }
          }
        }
      }

      private static class Win64
      {
        private struct PROCESS_MEMORY_COUNTERS_EX
        {
          public uint cb;
          public uint PageFaultCount;
          public ulong PeakWorkingSetSize;
          public ulong WorkingSetSize;
          public ulong QuotaPeakPagedPoolUsage;
          public ulong QuotaPagedPoolUsage;
          public ulong QuotaPeakNonPagedPoolUsage;
          public ulong QuotaNonPagedPoolUsage;
          public ulong PagefileUsage;
          public ulong PeakPagefileUsage;
          public ulong PrivateUsage;
        }

        [System.Runtime.InteropServices.DllImport("Psapi.dll")]
        private static extern long GetProcessMemoryInfo (long process, ref PROCESS_MEMORY_COUNTERS_EX x, uint cb);

        [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
        private static extern long GetCurrentProcess ();

        public static void GetMemorySize (out long virtualSize, out long residentSize)
        {
          PROCESS_MEMORY_COUNTERS_EX x = new PROCESS_MEMORY_COUNTERS_EX();
          x.cb = 80;
          GetProcessMemoryInfo(GetCurrentProcess(), ref x, 80);
          virtualSize = (long)x.PrivateUsage;
          residentSize = (long)x.WorkingSetSize;
        }
      }

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Утечка виртуальной памяти
« Ответ #14 : Март 20, 2012, 11:16:51 am »
Посмотрел исходники top и atop - таки они под линуксом реально парсят /proc/pid/stat.
А ты случайно не обратил внимание на то, с какой максимальной частотой они туда могут смотреть? Хочется узнать с какой максимальной частотой имеет смысл смотреть в proc. Я сейчас это делаю 10 раз в секунду, но вдруг там данные обновляются реже? Тогда и я реже буду смотреть.