На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
В этом разделе можно создавать темы, которые относятся к поколению 32-битных компиляторов.
Здесь решаются вопросы портирования кода из старого доброго Турбо Паскаля в FPC, TMT, VP, GPC компиляторы, а также особенностей программирования на них для Windows/Linux и других ОС.
Указывайте тип компилятора, его версию, а также платформу (Windows/Linux/..) компиляции, другими словами, Target.
Модераторы: volvo877
  
> "Прожорливый Lazarus/FreePascal для Memo" , Подскажите, что я делаю не так? Память утекает как из водопада...
    Не понимаю почему мемо в лазарусе "кушает" так много памяти?

    Дано:
    Форма, на ней два мемо (WordWrap=false)
    Загрузку данных в мемо выполняю через memo1.Lines.LoadFromFile('testfilename.txt');
    Пишем процедуру типа:
    ExpandedWrap disabled
      procedure flip;
      var t:string;
      begin
      t:=Form1.Memo2.text;
      Form1.Memo2.text:=Form1.Memo1.text;
      Form1.Memo1.text:=t;
      t:='';
      end;

    Потребление смотрю через вин7 таскмэнеджер.

    Запускаем программу - занимает 2-3Мб.
    Загружаем данные в мемо (размер файла 53Мб), в момент загрузки потребление выростает до 289Мб, когда файл загружен, памяти занято 115Мб.
    Выполняем процедуру flip - 375Мб ,385Мб, данные из первого мемо пропали, отобразились во втором - занимаем памяти 224Мб.
    224Мб для хранение 50ти?
    Запускаю повторно флип, в пиковый момент программу использует 424Мб-600Мб оперативки, потом сново спускается до 224Мб.

    Я с ума сошел или в чем дело? В винде, лазарусе, компилляторе, или всетаки в моем незнании (хотелось бы верить в последнее).
    Была мысль что файл анси, а контроллы лазаруса в юникоде, но у меня в файле только цифры, хотя если лазарус использует какой-нибудь Big Endian (а не utf8).
    С другой стороны 53Мб - обьем всего файла в аски, а не кол-во символов которые я кинул в мемо (через скажем копи-пэйст).
    Гуру просвятите плиз.
    Прикреплённый файлПрикреплённый файлlab_memo_flip.rar (63,14 Кбайт, скачиваний: 286)
    Сообщение отредактировано: volvo877 -
      Не надо полагаться на TaskManager в вопросах использования памяти. Ни к чему хорошему это не приведет. Загрузил в Memo файл в 63Мб (под Memory Size показало мне 330 Мб), сделал Flip - показало 94 Мб после завершения обмена, а теперь - внимание, чудо: минимизируем приложение, и памяти используется... Сколько? :) Правильно, меньше 1 Мб (восстанавливаем - вырастает до 2.2, не больше).

      Все дело в том, что TaskMan показывает Working Set, а не память, выделяемую приложением. А это разные вещи.
        2 volvo877, благодарю за пояснение!
        Сорри, что код в теги не взял как следует.
        Скажите, а какая у Вас ОС? Я приложение минимизировал, размер не уменьшился, так и остался 223Мб.
        Оценил поведение поп sysinternals "Process Explorer" (активировал все колонки для замеров памяти, кроме всяких page fault), также в процесс вьювере фаервола - цифры примерно такиеже.
        Как иначе более точно оценить использование памяти? И главное что с этим делать, от мемо отказаться не могу, как и от лазаруса для этого проекта. Может в компилляторе есть опция какая-нибудь, чтобы оптимизировать работу с памятью для мемо?
          Цитата yourpc @
          Может в компилляторе есть опция какая-нибудь, чтобы оптимизировать работу с памятью для мемо?

          TMemo основан на стандартном виндовом контроле, поэтому единственной опцией м.б. только использование юникод- или анси-версии этого контрола. Судя по всему юзается юникод, поэтому размер текста, хранимого в мемо, удваивается по сравнению с аски-файлом (и никакие utf8 и ascii тут ни причем, т.к. если контрол юникодный, то текст в нем хранится в utf16)

          PS: Не понятны две вещи: 1) зачем грузить такие объемные файлы в Мемо - кто их читать-то будет?!, 2) стоит ли под вин7 беспокоиться о каких-то "жалких" 100-200Мб памяти?!
          Сообщение отредактировано: leo -
            2 leo, я примерно так и подумал. Не понятно почему утф16, а не утф8 н.р., что было-бы экономнее.
            1) файлы в мемо нужно грузить и более обьемные (возможно даже на порядок) - такие условия задачи. Уже была мысль сделать разбитие файла на страницы и загружуать из памяти только необходимые данные, но для этого придется свой скролл-бар делать.
            2) стоит, если для флипа 50Мб в некоторые моменты сисетма использует до 600Мб, ладно бы 100, но даже по завершении флипа зарезервировано оставется 220Мб. Да и вообще, думаю всегда стоит беспокоится о таких утечках, мне просто не приятно с такой программой работать, а особенно осознавать что я приложил руку к ее созданию. Потом кто-нибудь из Вас будет ее допиливать, и ругать меня самыми нелестными словами, а у меня уши гореть :)))


            Может какой-нибудь контролл другой использовать (с синедит таже ерунда, правдо при загрузке данных из файла скачки в памяти не такие значительные).
              Цитата yourpc @
              стоит, если для флипа 50Мб в некоторые моменты сисетма использует до 600Мб, ладно бы 100, но даже по завершении флипа зарезервировано оставется 220Мб

              А сколько по твоему должно быть после двух флипов, если в одном мемо уже было 110Мб - перекочевало во второй и добавилось еще 110 в первый?
              Что касается "некоторых моментов", то ты понимаешь, что делает твой флип? Первая строчка t:=Form1.Memo2.text создает копию текста мемо = увеличение до двух раз, если используется юникод, или до полутора, если utf8. Во второй строчке - создание временной копии строки Form1.Memo1.text, т.е. еще одно увелиичение. Причем, если в лазарусе используется string в utf8, то требуемый объем памяти еще возрастает, т.к. сначала из мемо читаются данные в utf16, а затем они преобразуются в utf8
              Сообщение отредактировано: leo -
                2 leo, только флип после копирования данных освобождает предидущее мемо (тоесть это не копирование данных а обмен данными между двумя мемо).
                Я понимаю причины "скачков" памяти, но не понимаю почему для текста в 50Мб в конечном итоге используется 220Мб памяти, ведь второй мемо изначально пустой.

                По поводу строки - это идея, может вместо стринг действительно следует использовать вайдстринг (сам стринг понятно не утф а обычный анси)!

                Добавлено
                "...если в одном мемо уже было 110Мб - перекочевало во второй и добавилось еще 110 в первый?..."
                110 в другой мемо не добавляется, а если добавляется, то обнуляется в первом. По условию загрузку данных я произвожу только в первый мемо.
                  Цитата yourpc @
                  2 leo, только флип после копирования данных освобождает предидущее мемо (тоесть это не копирование данных а обмен данными между двумя мемо).

                  Если тебе нужна очистка, то и используй Memo.Clear. А при присвоении текста Memo.text:=... винда не обязана анализировать текст и освобождать или реаллоцировать используемый буфер, если его хватает для хранения нового текста. Вот у тебя, видимо, и получается, что при Memo1.Load... виндой выделяется 100Mb-буфер под текст, а при последующем присвоении Memo1.text:=Memo2.text этот буфер не уменьшается, а остается тем же самым, хотя и хранит "пустой текст"

                  Добавлено
                  Обмен данными между мемо можно сделать без всяких доп.затрат памяти на уровне обмена хэндлов виндовых буферов:
                  ExpandedWrap disabled
                    procedure flip(M1,M2:TMemo);
                    var
                      h1,h2:cardinal;
                    begin
                      h1:=SendMessage(M1.Handle,EM_GETHANDLE,0,0);
                      h2:=SendMessage(M2.Handle,EM_GETHANDLE,0,0);
                      SendMessage(M1.Handle,EM_SETHANDLE,h2,0);
                      SendMessage(M2.Handle,EM_SETHANDLE,h1,0);
                    end;

                  Хотя смысл этого flip не понятен, и обмен буферов не решит проблемы, если в Memo2 будет буфер избыточного размера

                  Добавлено
                  PS: Аналогично можно проверить и размер буфера, если после получения хэндла вызвать LocalSize(h1)
                  Сообщение отредактировано: leo -
                    Кстати, не знаю как в лазарусе, но в дельфи7 ни Memo1.Text:='', ни Memo1.Clear, ни SendMessage WM_CLEAR не приводят к уменьшению размера ранее выделенного большого буфера. Реально работает только SetWindowText(Memo1.Handle,nil) и ее эквивалент SendMessage(Memo1.Handle,WM_SETTEXT,0,0).
                    А если вместо nil\0 передать пустую строку '', как делается в дельфях, то реально передается не nil, а указатель на 0-символ, и реаллокации буфера при этом не происходит

                    Добавлено
                    PS: Еще Memo.SetTextBuf(nil) сбрасывает буфер, а Memo.SetTextBuf('') - нет
                    Сообщение отредактировано: leo -
                      2 leo, К сожалению винапи использовать не могу, так как программа будет использоваться не только в вин, точнее под вин я ее только дорабатываю, так как мне привычнее. С clear возможно имеет смысл, возможно не под вин работа с памятью будет реализована иначе. Флип это пример-иллюстрация для того чтобы показать что происходит с памятью, в реальной задаче придется обменивать буферы разной (значительно разной) длины. На самом деле, то что я вызываю clear или присваиваю '' не должно сразу менять размер выделенного блока памяти. В любом случае благодарю за участие, появились некоторые новые мысли. Пока попробую реализовать через указатели.
                        Цитата yourpc @
                        К сожалению винапи использовать не могу

                        Memo.SetTextBuf(nil) ?
                          Memo.SetTextBuf(nil) - никак не влияет на кол-во потребляемой памяти. Тестировал правдо через таскмэнеджер в вин7, потом еще через другие утилиты погляжу, но чисто визуально все также как и :=''
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0349 ]   [ 18 queries used ]   [ Generated: 28.03.24, 14:21 GMT ]