OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 20 Июнь, 2025 01:46

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 12 ] 
Автор Сообщение
СообщениеДобавлено: Понедельник, 26 Июль, 2010 23:40 

Зарегистрирован: Среда, 04 Июль, 2007 16:43
Сообщения: 247
Есть ли у BB внутреннее ограничение на размер аллокированной памяти?
При попытке зааллокировать максимально возможное количество памяти
Код:
MODULE TestAllocate;
   IMPORT Log := StdLog;
   PROCEDURE Do* (bits: INTEGER);
      VAR a: ARRAY 64 OF POINTER TO ARRAY OF REAL;
         n, i, j: INTEGER;
         mem, memtot: REAL;
   BEGIN
      n := ASH(1, bits); memtot := 0; j := 0;
      NEW(a[j], n);
      WHILE (j < 64) & (a[j] # NIL)DO
         FOR i := 0 TO n - 1 DO
            a[j, i] := 0
         END;
         mem := n * SIZE(REAL) / 1024. / 1024.;
         memtot := mem + memtot;
         Log.Int(j); Log.String(":"); Log.Tab;
         Log.Real(mem); Log.String(" MB"); Log.Tab;
         Log.Real(memtot); Log.String(" MB"); Log.Ln;
         INC(j);
         IF j < 64 THEN NEW(a[j], n) END
      END;
      IF j < 64 THEN Log.String("Not enough memory"); Log.Ln END;
      FOR j := 0 TO 63 DO
         a[j] := NIL
      END
   END Do;

END TestAllocate.

^Q"TestAllocate.Do(24)"

BB останавливается на ~1.4-1.5 ГБ, причем как на машине с 2 ГБ памяти, так и на машине с 6 ГБ памяти. При этом на 6 ГБ машине удается запустить вторую копию BB, в которой также можно аллокировать до 1.5 ГБ, т.е. память вроде доступна ОС, но не доступна BB.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 27 Июль, 2010 00:52 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Что нужно учитывать:
- в Win32 процессу доступно виртуальное адресное пространство 2Гб, не более того. Дальнейшие адреса зарезервированы для ОС (туда идёт мэппинг системных библиотек, KERNEL32, насколько помню, как раз там же и т.п., хотя для пользователя совершенно неясно, подо что так много зарезервировано). Есть у NT начиная с 2000-го ключик в boot.ini, который отдаёт процессам 3Гб адресного пространства.
- если запуск идёт на Win64, то там вообще какие-то свои законы для 32-разрядной подсистемы.
- некоторое количество памяти отжирают служебные структуры кучи. Но, конечно, не 0.4 Гб, тем более, что у Вас несколько крупных объектов.
- эффективно распределить 0.4 Гб может оказаться невозможным из-за фрагментации. Там просто реально может не найтись непрерывного куска 130Мб, который Вы просите очередным NEW. Там ведь сидят модули, DLL-ки, наконец, сама WinApi в графическом приложении наверняка имеет выделенную память в пользовательском пространстве, в системной куче процесса (WinApi.HeapAlloc).

В общих чертах так.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 27 Июль, 2010 01:07 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Вот как работает диспетчер кучи ББ (в основном режиме, там есть ещё режим для случая DLL - когда блоки запрашиваются у стандартного системного HeapAlloc).
Код:
   PROCEDURE AllocHeapMem (size: INTEGER; VAR c: Cluster);
      (* allocate at least size bytes, typically at least 256 kbytes are allocated *)
      CONST M = 1536 * 100000H;   (* 1.5 GByte *)
      CONST N = 65536;   (* cluster size for dll *)
      VAR adr, s: INTEGER;


ББ пытается зарезервировать под свою кучу в адресном пространстве процесса кластер размером начиная с M байт (деля M пополам, если не получилось, пока не получится). Резервируются только адреса (reserve виртуальной памяти).
Таким образом, при старте ББ резервируется 1 кластер памяти 1.5 Гб, в рамках которого идёт реальное выделение блоков (commit зарезервированных адресов) и отдача их под динамические объекты.

Как только этот 1.5 Гб кластер вычерпан, происходит выделение ещё одного кластера. Тем же путём 1.5Гб делится на два, пока не удастся выделить такой кусок. Т.е. следующий кластер будет 201 Мб (т.к. 406 не влезет никак) или меньше, как повезёт. Потом - 100, а у Вас размер одного массива - 134 Мб.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 27 Июль, 2010 12:03 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Ещё замечено, что под 32-битной Windows XP иногда удаётся взять у системы почти два гига, а в 32-битной Windows 7 удаётся взять то ли всего полтора, то ли 1.7, вобщем поменьше (на компе с семёркой у меня видюха интегрёная, может быть из-за этого?).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 28 Июль, 2010 00:11 

Зарегистрирован: Среда, 04 Июль, 2007 16:43
Сообщения: 247
Илья Ермаков писал(а):
Как только этот 1.5 Гб кластер вычерпан, происходит выделение ещё одного кластера. Тем же путём 1.5Гб делится на два, пока не удастся выделить такой кусок.

Спасибо!
Посмотрев код Kernel, мне правда кажется, что в случае dllMem = FALSE, AllocHeapMem вызывается только один раз при инициализации, а наращивание памяти происходит только за счет GrowHeapMem в пределах одного кластера root. Т.е. при инициализации BB пытается зарезервировать 1.5 ГБ памяти или меньше (1.5/2, 1.5/4, ...) и дальнейшее реальное выделение блоков происходит только в пределах изначально зарезервированного пространства. И, как следствие, BB в не dll-моде в принципе не может взять у системы больше этих самых 1.5 ГБ. Может такое быть?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 28 Июль, 2010 10:15 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Да, Вы действительно внимательно посмотрели.
В NewBlock AllocHeapMem вызывается только в ветке dllMem, на что я вчера ночью не обратил внимания :)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 28 Июль, 2010 23:20 

Зарегистрирован: Среда, 04 Июль, 2007 16:43
Сообщения: 247
Что вызывает удивление, так это работа сборщика мусора. Cначала запускаю приведенную выше программу с аллокацией блоков по 128 МБ, удается зааллокировать 1.4 ГБ. ОК. Затем запускаю ту же программу с аллокацией блоков по 32 МБ (TestAllocate4.Do(22)). Удается зааллокировать 1.1 ГБ. Ладно. Теперь опять пытаюсь аллокировать блоки по 128 МБ: не удается зааллокировать ни один блок! Казалось бы, сборщик мусора должен при первом требовании освободить место в изначально выделенном адресном пространстве, поскольку на элементы массива после отработки программы ссылок уже нет? Services.Collect ситуации не меняет. Правда, если многократно запускать TestAllocate4.Do(24), то в какой-то момент удается таки зааллокировать первые 128 МБ, затем больше и в конце-концов опять дойти до 1.4 ГБ! Т.е. сборщик мусора в конце-концов таки срабатывает, правда отдает блоки памяти очень неохотно. Такое поведение это что - особенность реализации сборки мусора или все-же баг??


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 28 Июль, 2010 23:54 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Ну да... Потому что фактически освободившиеся блоки не расформировываются, они висят в списке старых, для повторного использования... В случае ~dllMem, опять же.

Там ряд аспектов в плане стратегии может быть модифицирован, если понимать, подо что тюнить.

Хотя для динамического распределения больших линейных областей памяти как-то массивы не всегда применяют. Иногда делают что-то типа Files.File в памяти - и элементы оттуда считывают/записывают. Тогда и на диск прозрачно свопить можно.
Обычная динамическая память хороша, когда много мелких объектов, ссылающихся друг на друга. Граф связей, динамика.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 29 Июль, 2010 09:29 

Зарегистрирован: Пятница, 13 Март, 2009 16:36
Сообщения: 989
Откуда: Казань
Проблема с тем что после выделения блоков по 32 мегабайта не удается затем выделить блоки по 128 мегабайт. Может быть из-за фрагментированности кучи. После выделения 32 мегабайт, BB может выделить сколько-нибудь памяти для своих нужд, например, если вы выводите какую-нибудь информацию в Log, затем 32 мегабайтные блоки уже не нужны, а та память которую использует BB еще нужна. Поэтому не оказывается свободных блоков по 128 мегабайт.
Попробуйте посмотреть в BB Info->Heap Spy...->Show Heap.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 29 Июль, 2010 11:05 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
32-мбайтные блоки висят в списке свободных блоков, а не расформировываются в просто свободное пространство. В этом и нюанс.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 31 Июль, 2010 15:16 

Зарегистрирован: Среда, 04 Июль, 2007 16:43
Сообщения: 247
Rifat писал(а):
Попробуйте посмотреть в BB Info->Heap Spy...->Show Heap.

Кстати, при попытке использования Show Heap в указанном примере происходит ошибка (видимо при больших размерах выделенной памяти где-то происходит переполнение).


Вложения:
trap.PNG
trap.PNG [ 37.85 КБ | Просмотров: 10802 ]
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Суббота, 31 Июль, 2010 18:38 
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Угу, там слишком большой вертикальный размер вьюхи-карты, 36000 * размер_в_мм перепрыгивает за ёмкость INTEGER.

Вьюхи, которые могут быть большого размера, должны делаться уже с custom-прокруткой (обрабатывать сообщение PollSectionMsg и ScrollMsg), а эта сделана "в лоб".


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2025, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB