Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Array of ... и исключение out of memory, помогите разобраться 
:(
    Опции темы
DASTAD
Дата 12.6.2011, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 14.10.2009

Репутация: 1
Всего: 1



Прошу помощи.
Пишу небольшое приложение мониторинга БД для себя. По задумке прога должна считывать инфу из БД раз в 30 сек, делать кое какие расчеты и вывести на экран. Вылетает применро через 4-5 часов работы с исключением Out of Memory. Как избежать Out of Memory. Интересны любые предложения smile
Заранее благодарен!

В проге использую следущую структуру данных
Код

   {измерения}
   TMonRec = record
     A,B: real; 
     AVN, BVN: real; 
     DSV, DBV: real; 
     T: TDateTime;
     f: ShortInt; 
   end;

{объекты мониторинга}
  PMonObject = ^TMonObject;
  TMonObject = class
    History: array of TMonRec;
    Count: integer;

     {другие переменные класса}
     {функции класса}
  end;

{общий список объектов}
   PMonList = ^TMonList;
   TMonList = class
     Count: integer;      
     Mon: array of PMonObject;
     {другие переменные класса}
     {функции класса}
  end;


Общее описание работы
В классе MonList раз в 30 сек вызывается метод Work, который перебирает все элементы массива Mon: PMonObject и запускает их фунцию Work. В функции TMonObject.Work происходит считывание из БД, некие вычисления и запись результата в память HistoryAdd. 
код HistoryAdd
Код

procedure TMonObject.HistoryAdd;
var last: integer;
     begin
       Count:=HisCount+1;
       SetLength(History, Count);
       last:=HisCount-1;
       History[last].T:=hT;
       History[last].A:=hA;  
       History[last].B:=hB;
                     ...
     end;


При моем количестве объектов 250-300 и количестве измерений за день ~1000 -1500 такая структура должна занимать в памяти ~16-32 Мегабайт ;)

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

ЗЫ На компе 8гиг оперативки ОС Win7x64 и SQL Server 2005 64bit
В диспетчере задач отображается, что моя програ занимает порядка 250-300 Мегабайт, порядка 500 SQL server и порядка 150-250 та прога, которая заносит информацию в БД. Общая используемая память в системе порядка 5,5 Гигабайт.

PM MAIL   Вверх
northener
Дата 12.6.2011, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



Имхо, происходит фрагментация памяти из-за многочисленных 
Цитата

SetLength(History, Count);



--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
DASTAD
Дата 12.6.2011, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 14.10.2009

Репутация: 1
Всего: 1



Цитата(northener @ 12.6.2011,  16:53)
Имхо, происходит фрагментация памяти из-за многочисленных 
Цитата

SetLength(History, Count);

тогда, так понимаю, лучше сразу на N измерений выделить?
после заполнения еще на N
PM MAIL   Вверх
bems
Дата 12.6.2011, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(DASTAD @  12.6.2011,  18:41 Найти цитируемый пост)
после заполнения еще на N 

есть мнение что каждый раз в два раза будет лучше.


--------------------
Обижено школьников: 8
PM MAIL   Вверх
northener
Дата 13.6.2011, 02:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



Цитата(DASTAD @  12.6.2011,  18:41 Найти цитируемый пост)
тогда, так понимаю, лучше сразу на N измерений выделить?
после заполнения еще на N 

Тогда прога вылетит с ошибкой out of memory "на сколько-то позже чем через 4-5 часов".
Не лучше ли не изгаляться так над "оперативной памятью программы", а использовать, ну например дисковую память?
Записывать эту историю каждый раз на диск. Тогда и от динамических массивов можно отказаться в пользу статических.  Что явный плюс при "долговременно-непрерывной" работе программы. 

P.S. Имею некоторый опыт разработки и поддержки программ, которые должны работать постоянно. Т.е. круглосуточно 365 дней в году, а раз в 4 года так и вовсе 366! smile


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
RomanEEP
Дата 15.6.2011, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 5
Всего: 8



1)PMonObject = ^TMonObject; для чего?!!! объект это уже и так указатель. Тип PMonObject нужно выкинуть, ссылки на него заменить на TMonObject
2)Проблема с Out of memory мне кажется из-за того что система не может выделить непрерывный кусок памяти под History: array of TMonRec;
выход переделать TmonRec = record на TmonRec = class, а History сделать TList-ом
PM MAIL   Вверх
Чучмек
Дата 20.6.2011, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 14
Всего: 41



Цитата(DASTAD @  12.6.2011,  16:47 Найти цитируемый пост)
 Count:=HisCount+1;
       SetLength(History, Count);


Цитата(DASTAD @  12.6.2011,  18:41 Найти цитируемый пост)
тогда, так понимаю, лучше сразу на N измерений выделить?
после заполнения еще на N 


Цитата(bems @  12.6.2011,  20:19 Найти цитируемый пост)
есть мнение что каждый раз в два раза будет лучше. 


А для чего служит резервирование?

Код

const memory_page_size=65536;

var  allocated_memory_size:cardinal;

procedure myAddElement(pm:pointer;count,el_size:cardinal); //Увеличение размера  массива. 
// pm-вариантный массив как указатель; 
// count-на сколько элементов увеличить размер массива
// el_size-размер элемента массива 
var p_array_length:pcardinal;  
begin
p_array_length:=pointer(cardinal(pm)-4); //указатель на размер массива
while 8+el_size*(count+p_array_length^)>allocated_memory_size do   // пока памяти выделенно меньше, чем необходимо для размешеня новых элементов
  begin
  VirtualAlloc(pointer(cardinal(pm)-8+allocated_memory_size),memory_page_size, MEM_COMMIT, PAGE_READWRITE);//Выделить страницу памяти 
  allocated_memory_size:=allocated_memory_size+memory_page_size;
  end;
p_array_length^:=p_array_length^+count;
end;


type tm=array of myType;

var 
m:tm //мой вариантный массив
p:pointer;
max_size:cardinal:=256*256*256*64; //размер резервируемой памяти

//инициализация массива
begin
allocated_memory_size:=memory_page_size;
p:=VirtualAlloc(nil,max_size,MEM_RESERVE or MEM_TOP_DOWN,PAGE_READWRITE);//резервируем память(адресное пространство)
VirtualAlloc(p,memory_page_size, MEM_COMMIT, PAGE_READWRITE);//выделяем страницу памяти
pinteger(p)^:=0;             //счетчик ссылок
pinteger(cardinal(p)+4)^:=0; //размер массива
m:=pointer(cardinal(p)+8); //сам массив
end;


//Заполнение массива
for i:=0 to 256*256*12 do
 begin
 myAddElement(pointer(m),1,sizeof(m[0]));
 m[i]:=i;
 end;


//освобождение массива
pinteger(p)^:=0;//Важно !!!
m:=nil;
VirtualFree(p,0,MEM_RELEASE);



Вызов SetLength для такого массива не допустим!!! Только myAddElement!!!
Для каждого массива allocated_memory_size должен быть свой!!!
Если необходимо несколько массивов, лучше создать свой класс.
Если есть нечто типа m2:=m, то обязательно m2:=nil перед вызовом VirtualFree!!!

p.s.
Вряд ли  получиться зарезервировать более 2Гбайт.
У меня получилось только 1543503872 байт.
Нет такого цельного куска в адресном пространстве процесса.


Это сообщение отредактировал(а) Чучмек - 21.6.2011, 15:39


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0464 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.