На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> меньше памяти
    Цитата uk- @
    Я не то что жалуюсь на то что у меня много памяти жрёт, а просто спрашиваю как можно с экономить её..

    Встречал несколько способов.
    Первый опробовал сам, еще в пятом дельфи. Отказ от VCL, все формы выполнены в виде диалогов, и хранятся в ресурсах. Сложность разработки увеличивается не на много, зато прога содержащая более двух сотен кнопок (ownerdraw), едитов и диалогов, создающая несколько потоков(для работы с железом) и содержащая элементы анимации кушает 1.4 Мб памяти, т.е. то что виндовс по умолчанию выделяет любой запускаемой программе.
    Так же встречал другой любопытный способ. Сама программа написана без VCL, и представляет собой лишь обработчик сообщений, но все что связано с интерфейсом заделано на VCL, и скомпилировано в DLLы, подгружаемые и выгружаемые по мере необходимости. По моему самый лучший вариант для тех, кому удобство VCL превыше всего :yes:
    Цитата uk- @
    параметр в функцию передавть как var либо const что бы не копировало в стек лишнюю память

    Это помимо всего еще и на быстродействии хорошо скажется :yes: А насчет стека могу сказать только то что виндовс по умолчанию выделяет под него небольшой клочок памяти, и если происходит выход за его пределы, то выделяется еще один кусочек, и т.д., пока не будет исчерпан лимит на макс. размер стека программы, после чего есть шанс увидеть "Программа выполнила недопустимую операцию" © :lol:
      Цитата uk- @
      параметр в функцию передавть как var либо const что бы не копировало в стек лишнюю память

      Только нет смысла передавать небольшие параметры вроде Integer, Boolean таким образом, потому что на передачу адреса этой переменной будет потрачено такое же количество памяти. Так что перебарщивать код лишними const-ами нет смысла.
        Цитата uk- @
        да знаю я где смотреть и сколько её там.. ВОПРОС не в этом..


        Ну ты даёшь. Тебе хочется уменьшить память программы, а ты не знаешь вообще сколько она жрёт, но каким то сверхчуствительным органом определяешь на всзгяд - какое приложение сколько жрёт памяти...
        Я конечно многово повидал, но такого...

        Диспетчер задач - процессы - Память. В процессах находишь своё приложение и смотришь память...

        Вот и отталкивайся.
          :blink: :blink: Я в шоке!
          Цитата
          да знаю я где смотреть
          и сколько она жрёт !
          Цитата
          ВОПРОС не в этом..
          ..
          ..
          Цитата
          Я не то что жалуюсь на то что у меня много памяти жрёт, а просто спрашиваю как можно с экономить её..

          Что не понятного? тут не говорится о чём то конкретном, а вообще способы уменьшения используемой памяти, программой..
            Цитата n0wheremany @
            Диспетчер задач - процессы - Память. В процессах находишь своё приложение и смотришь память...

            Цитата uk- @
            да знаю я где смотреть
            и сколько она жрёт !

            А какую такую память нам показывает диспетчер задач и кто "жрет" память ?
            Берем элементарную прогу "Hello, World!" на асме со совмещенной секцией кода\данных\импорта. На диске она занимает всего 2*512=1К, а при загрузке в память сам образ всего - 2*4К=8К. Плюс стэк 8К и главная куча 12К (и там и тут загрузчик уже успел "наследить"). Итого нашего "родного" всего 28К, хотя ради справедливости сюда нужно еще добавить секции данных подгруженных системных dll ~13*4К=52К, итого в сумме 80К. А диспетчер на старте проги (до вывода MesssageBox) показывает аж 568К. Значит винда "вешает" на наш процесс всю свою внутреннюю обслугу процесса. Это и служебные данные, явно спроецированные в процесс (PEB, TEB, environment strings, список загруженных модулей LDR_DATA и еще вагон и маленькая тележка всякого "хлама"), и куча всякого скрытого добра типа таблиц страниц, объектов ядра и еще х.з.чего. Дальше еще интереснее - когда выскакивает MessageBox "занимаемая" память увеличивается до 1.2Mб пока окно сидит в трее (как мин.подгружаются еще 3 dll) и до 1.4Mб при активизации окна. Вот после этого и думай как "сэкономить память" :wacko: Разумеется нельзя расточительно обращаться с памятью, но и мелочная экономия тут тоже не имеет никакого смысла. В частности передавать структуры по ссылке хорошо в плане быстродействия, но к экономии памяти это не имеет никакого отношения ;)
              Цитата leo @
              В частности передавать структуры по ссылке хорошо в плане быстродействия, но к экономии памяти это не имеет никакого отношения ;)

              почему? а если передать по значению например 10 000 символов строки?
                Цитата uk- @
                а если передать по значению например 10 000 символов строки?

                а если 2Гб символов(строки могут быть такой длины)?

                ЗЫ я к тому, что некоторые структуры всегда передаются по ссылке...
                  буфер :whistle:

                  -Added
                  Цитата Shaggy @
                  ЗЫ я к тому, что некоторые структуры всегда передаются по ссылке...

                  ладно спасибо
                    Цитата uk- @
                    почему? а если передать по значению например 10 000 символов строки?

                    Потому что, во-первых, динамические строки и массивы по любому передаются по ссылке, а в стек копируются только статические массивы, во-вторых, 10К это мелочь по сравнению с 1.4М и к тому же из этих 10К нужно вычесть уже выделенную под стек память. В приведенном выше примере на старте проги под стек уже выделено 8К физ.памяти, но реально используется менее сотни байт, поэтому при запихивании в стек 10К его реальный размер возрастет только на 4К. Разумеется злоупотреблять передачей больших массивов по значению, также как и объявлять их в качестве локальных переменных нельзя, т.к. физ.память, выделенная под стек не освобождается - локальные переменные формально "уничтожаются", но лишь в том смысле, что при выходе из процедуры указатель стека автоматически возвращается к первоначальному значению и при вызове другой процедуры новые локальные переменные будут записываться на место "старых".

                    Но выделять локальные буферы до единиц-десятков Кб вполне допустимо и даже может иметь определенные преимущества по сравнению с GetMem, т.к. позволяет избежать или уменьшить фрагментацию кучи. Например, что может произойти и часто происходит при чтении файлов. Выделяем в куче буфер большого размера через GetMem или SetLength, читаем файл, обрабатываем и не освободив буфер выводим сообщение в глобальнцю строку, например Label1.Caption. Если куча не фрагментирована и в ней не нашлось подходящей "дырки" под строку, то строка будет выделена в конце кучи после буфера. В этом случае после освобождения буфера в куче образуется большая дыра и выделенная память не уменьшается, т.к. менеджер памяти освобождает страницы (decommit) только с хвоста кучи, который в данном случае занят строкой. Примерно то же происходит и при TStringList.LoadFromFile - в результате загрузки занимаемая память может увеличиваться более чем на 2 размера файла, т.к. текст сначала целиком грузится в темп-строку, а потом разбивается на отдельные строки, которые размещаются в куче после темп-строки. Если же читать файл в "сторонний" буфер (локальный или Heap\VirtualAlloc), то подобных больших дыр в куче не возникает.
                      Цитата leo @
                      В приведенном выше примере на старте проги под стек уже выделено 8К физ.памяти, но реально используется менее сотни байт, поэтому при запихивании в стек 10К его реальный размер возрастет только на 4К

                      Верно, но теперь представь что в процедуре есть локальная переменная, куда при обработке помещается переданный массив. Вот и еще возврастание стэка на 3 страницы. А ведь стек жрет физическую память, и как ты верно заметил:
                      Цитата leo @
                      физ.память, выделенная под стек не освобождается

                      Так что как ни крути, а с памятью нужно поосторожнее работать. Сам ведь небось встречался с ситуацией, когда в стек пытаются десятки мегов данных запихать :lol: Самое хреновое, что Дельфи тупо пытается это сделать, на что справедливо получает Stack Overflow :wacko:
                        Цитата AndNot @
                        Так что как ни крути, а с памятью нужно поосторожнее работать

                        Я бы сказал не "поосторожнее", а с умом и со знанием дела ;) Тогда и переполнения стека не будет и память будет использоваться рационально - без излишеств и злоупотреблений, но и без мелочной параноидальной экономии ;)

                        И твоего восхищения "любопытным" и "самым лучшим" способом динамической загрузки\выгрузки VCL-библиотек я не понимаю :( Такое впечатление, что люди или застряли в прошлом веке MS DOS и слабеньких компов с парой мегабайт оперативы, или участвуют в каком то непонятном соревновании - у кого диспетчер задач меньше цифирек покажет :D . А что он на самом деле показывает - фиг его знает. Но как бы не критиковали MS за отдельные штучки, но управление виртуальной и физической памятью в виндах устроено очень разумно - по принципу "не чеши пока не чешется". Во-первых, если кто-то думает, что при "загрузке" приложения весь образ срузу загружается в ОЗУ, тот глубоко ошибается - код и данные подгружаются с диска динамически по мере обращения к еще незагруженным страницам. Поэтому если мы открыли увесистую многофункциональную прогу, выполнили пару действий и закрыли, то возможно, что значительная часть неиспользуемого кода и данных даже и не загружалась с диска. С dll ситуация несколько хитрее, т.к. если она грузится не по своему базовому адресу, то нужно переустанвить релоки\фиксапы, и делается ли это сразу за один раз или также динамически - я на сей момент не знаю (надо бы поэкспериментировать).
                        Во-вторых, если кто-то думает, что при освобождении памяти, например при "выгрузке" dll или SetProcessWorkingSetSize(..,-1,-1) винда срузу безвозвратно "уничтожает" выделенные страницы, то тоже ошибается - умная винда просто помечает соответствующие страницы как неприсутствующие в пространстве процесса и находящиеся в переходном состоянии. В этом состоянии они могут находится сколь угодно долго, пока жив процесс и есть достаточный запас свободных и обнуленных страниц ОЗУ. Если через какое-то время процесс снова обращается к переходной странице или заново "грузится" dll, то винда просто возвращает переходные страницы процессу, экономя при этом "время и деньги". Поэтому выкрутасы с SetProcessWorkingSetSize и загрузками\выгрузками dll это просто самообман - реально из ОЗУ может ничего не выгружаться, но формально мы можем гордиться тем, что это уже не мы занимаем память, а винда ;) В результате на общем занимаемом объекме ОЗУ это никак не сказавается, но зато сильно напрягает систему и "раскаляет" процессор лишними ненужными действиями (обработка только одного отказа страницы занимает несколько тысяч тактов). Поэтому лучше не ломиться в вотчину винды как слон в посудную лавку, а довериться ее менеджеру виртуальной памяти - он сам сделает что нужно и когда нужно, сам подгрузит код и данные по первому требованию, а в случае нехватки физ.памяти сам ее почистит, выбросив наиболее давно неиспользуемые страницы
                        Сообщение отредактировано: leo -
                          :yes:
                          leo,
                          хорошо сказано !

                          Добавлю немножко: работа с OLE-обьектами, а непосредственно динамические строки,
                          очень часто встречается необходимость акумулирования строки
                          string=string+... при работе с динамической строкой - это может стать "убийством" для винды если пытаться суммировать данные больших размеров в циклах. Лучше выделить необходимый обьем с запасом(любых размеров до 2 гиг) но одноразово, чем в динамике передергивать OLE-engine, который может зарыться на полчаса запросто, вошкаясь с копированием в своп и обратно.
                            Цитата leo @
                            И твоего восхищения "любопытным" и "самым лучшим" способом динамической загрузки\выгрузки VCL-библиотек я не понимаю

                            А можно факты? Ведь на предположениях и документации от мягкотелых далеко не уедешь :lol:
                            Цитата leo @
                            впечатление, что люди или застряли в прошлом веке MS DOS и слабеньких компов с парой мегабайт оперативы

                            [offtop] dos есть и в настоящем, не так давно вышел PTS DOS 32, причем недорого :) [/offtop]
                            У меня из знакомых только человек 10 имеют более-менее современные компы, остальные в лучшем случае какой-нибудь селерончик, мегагерц эдак на 300-1000 ;)
                            И я прекрасно знаю, что при наличии выбора, они всегда выберут ту прогу, которая менее требовательна к ресурсам, пускай даже за счет некоторого снижения функциональности :whistle:
                            Цитата leo @
                            но управление виртуальной и физической памятью в виндах устроено очень разумно - по принципу "не чеши пока не чешется".

                            Обычное заблуждение позволяющее наплевать на все детали и кодить как бог на душу положит. Так ведь удобнее. К чему лишние проблемы? У юзера прога сильно свопит? Так пускай тачку обновит, он ведь уже пол года не апгрейдил. Зато мне так легче :) Так что ли?
                            Цитата leo @
                            Поэтому если мы открыли увесистую многофункциональную прогу, выполнили пару действий и закрыли, то возможно, что значительная часть неиспользуемого кода и данных даже и не загружалась с диска.

                            Ага, особенно это заметно по программам написанным на дельфи VCL :lol: Ты пробовал замерять время загрузки той же VCL-проги на метр кода и какой либо сторонней?
                            Цитата leo @
                            винда срузу безвозвратно "уничтожает" выделенные страницы

                            Она всего лишь помечает участки памяти как свободные. И они имеют все шансы при нехватке физической памяти отойти другой программе :) В этом и состоит преимущество DLL. Так что это не самообман.
                            Цитата leo @
                            В результате на общем занимаемом объекме ОЗУ это никак не сказавается, но зато сильно напрягает систему и "раскаляет" процессор лишними ненужными действиями

                            Это не сказывается когда ОЗУ более чем достаточно, а вот при его нехватке это очень даже полезые "выкрутасы". Проверено сотни раз на слабеньких тачках :tong:
                            А насчет напряга системы, так извини, это неумелые программеры ее "раскаляют", которые по всяким пустякам заводят треды. А переключение задач знаешь во сколько тактов обходится? Причем зачастую там где можно и без тредов обойтись.
                            Цитата leo @
                            а довериться ее менеджеру виртуальной памяти

                            "На бога надейся, а сам не оплошай" © Народ.
                            Нельзя же все оставлять на откуп системе. Дружба с головой еще никому не вредила :)
                            Цитата AlexJ @
                            Лучше выделить необходимый обьем с запасом(любых размеров до 2 гиг) но одноразово

                            :yes: Именно. Только желательно "необходимый обьем" поточнее вычислить. Все таки ресурсы не безграничны, и нет ничего хуже спопищайся программы!
                              Цитата AndNot @
                              Дружба с головой еще никому не вредила

                              Вот-вот, и я о том же:
                              Цитата leo @
                              без излишеств и злоупотреблений, но и без мелочной параноидальной экономии

                              :D

                              Цитата AndNot @
                              А можно факты?

                              Какие ? Если о подгрузке данных и кода по "требованию", то это элементарно проверяется по замерам времени обращения к странице по rdtsc (этим способом можно, хотя и не очень надежно, определять совал ли кто уже нос в твой процесс, см. Еще один вариант IsDebuggerPresent по RDTSC). Также можно проверить и время обращения к страницам dll при первой и последующих загрузках, хотя это видно и на глаз - при первом запуске приложение грузится дольше, а при повторных быстрее - системный кэш рулит ;)
                                leo, спасибо за ссылочку :yes: Можно попробовать метод в качестве универсального "детектора вирусов" :D Ведь теоретически вирь, получив управление, вызовет подгрузку страниц. Или я ошибаюсь?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0524 ]   [ 16 queries used ]   [ Generated: 27.04.24, 07:04 GMT ]