Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[44.222.233.8] |
|
Сообщ.
#1
,
|
|
|
Не понимаю почему мемо в лазарусе "кушает" так много памяти?
Дано: Форма, на ней два мемо (WordWrap=false) Загрузку данных в мемо выполняю через memo1.Lines.LoadFromFile('testfilename.txt'); Пишем процедуру типа: 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) |
Сообщ.
#2
,
|
|
|
Не надо полагаться на TaskManager в вопросах использования памяти. Ни к чему хорошему это не приведет. Загрузил в Memo файл в 63Мб (под Memory Size показало мне 330 Мб), сделал Flip - показало 94 Мб после завершения обмена, а теперь - внимание, чудо: минимизируем приложение, и памяти используется... Сколько? Правильно, меньше 1 Мб (восстанавливаем - вырастает до 2.2, не больше).
Все дело в том, что TaskMan показывает Working Set, а не память, выделяемую приложением. А это разные вещи. |
Сообщ.
#3
,
|
|
|
2 volvo877, благодарю за пояснение!
Сорри, что код в теги не взял как следует. Скажите, а какая у Вас ОС? Я приложение минимизировал, размер не уменьшился, так и остался 223Мб. Оценил поведение поп sysinternals "Process Explorer" (активировал все колонки для замеров памяти, кроме всяких page fault), также в процесс вьювере фаервола - цифры примерно такиеже. Как иначе более точно оценить использование памяти? И главное что с этим делать, от мемо отказаться не могу, как и от лазаруса для этого проекта. Может в компилляторе есть опция какая-нибудь, чтобы оптимизировать работу с памятью для мемо? |
Сообщ.
#4
,
|
|
|
Цитата yourpc @ Может в компилляторе есть опция какая-нибудь, чтобы оптимизировать работу с памятью для мемо? TMemo основан на стандартном виндовом контроле, поэтому единственной опцией м.б. только использование юникод- или анси-версии этого контрола. Судя по всему юзается юникод, поэтому размер текста, хранимого в мемо, удваивается по сравнению с аски-файлом (и никакие utf8 и ascii тут ни причем, т.к. если контрол юникодный, то текст в нем хранится в utf16) PS: Не понятны две вещи: 1) зачем грузить такие объемные файлы в Мемо - кто их читать-то будет?!, 2) стоит ли под вин7 беспокоиться о каких-то "жалких" 100-200Мб памяти?! |
Сообщ.
#5
,
|
|
|
2 leo, я примерно так и подумал. Не понятно почему утф16, а не утф8 н.р., что было-бы экономнее.
1) файлы в мемо нужно грузить и более обьемные (возможно даже на порядок) - такие условия задачи. Уже была мысль сделать разбитие файла на страницы и загружуать из памяти только необходимые данные, но для этого придется свой скролл-бар делать. 2) стоит, если для флипа 50Мб в некоторые моменты сисетма использует до 600Мб, ладно бы 100, но даже по завершении флипа зарезервировано оставется 220Мб. Да и вообще, думаю всегда стоит беспокоится о таких утечках, мне просто не приятно с такой программой работать, а особенно осознавать что я приложил руку к ее созданию. Потом кто-нибудь из Вас будет ее допиливать, и ругать меня самыми нелестными словами, а у меня уши гореть )) Может какой-нибудь контролл другой использовать (с синедит таже ерунда, правдо при загрузке данных из файла скачки в памяти не такие значительные). |
Сообщ.
#6
,
|
|
|
Цитата yourpc @ стоит, если для флипа 50Мб в некоторые моменты сисетма использует до 600Мб, ладно бы 100, но даже по завершении флипа зарезервировано оставется 220Мб А сколько по твоему должно быть после двух флипов, если в одном мемо уже было 110Мб - перекочевало во второй и добавилось еще 110 в первый? Что касается "некоторых моментов", то ты понимаешь, что делает твой флип? Первая строчка t:=Form1.Memo2.text создает копию текста мемо = увеличение до двух раз, если используется юникод, или до полутора, если utf8. Во второй строчке - создание временной копии строки Form1.Memo1.text, т.е. еще одно увелиичение. Причем, если в лазарусе используется string в utf8, то требуемый объем памяти еще возрастает, т.к. сначала из мемо читаются данные в utf16, а затем они преобразуются в utf8 |
Сообщ.
#7
,
|
|
|
2 leo, только флип после копирования данных освобождает предидущее мемо (тоесть это не копирование данных а обмен данными между двумя мемо).
Я понимаю причины "скачков" памяти, но не понимаю почему для текста в 50Мб в конечном итоге используется 220Мб памяти, ведь второй мемо изначально пустой. По поводу строки - это идея, может вместо стринг действительно следует использовать вайдстринг (сам стринг понятно не утф а обычный анси)! Добавлено "...если в одном мемо уже было 110Мб - перекочевало во второй и добавилось еще 110 в первый?..." 110 в другой мемо не добавляется, а если добавляется, то обнуляется в первом. По условию загрузку данных я произвожу только в первый мемо. |
Сообщ.
#8
,
|
|
|
Цитата yourpc @ 2 leo, только флип после копирования данных освобождает предидущее мемо (тоесть это не копирование данных а обмен данными между двумя мемо). Если тебе нужна очистка, то и используй Memo.Clear. А при присвоении текста Memo.text:=... винда не обязана анализировать текст и освобождать или реаллоцировать используемый буфер, если его хватает для хранения нового текста. Вот у тебя, видимо, и получается, что при Memo1.Load... виндой выделяется 100Mb-буфер под текст, а при последующем присвоении Memo1.text:=Memo2.text этот буфер не уменьшается, а остается тем же самым, хотя и хранит "пустой текст" Добавлено Обмен данными между мемо можно сделать без всяких доп.затрат памяти на уровне обмена хэндлов виндовых буферов: 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) |
Сообщ.
#9
,
|
|
|
Кстати, не знаю как в лазарусе, но в дельфи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('') - нет |
Сообщ.
#10
,
|
|
|
2 leo, К сожалению винапи использовать не могу, так как программа будет использоваться не только в вин, точнее под вин я ее только дорабатываю, так как мне привычнее. С clear возможно имеет смысл, возможно не под вин работа с памятью будет реализована иначе. Флип это пример-иллюстрация для того чтобы показать что происходит с памятью, в реальной задаче придется обменивать буферы разной (значительно разной) длины. На самом деле, то что я вызываю clear или присваиваю '' не должно сразу менять размер выделенного блока памяти. В любом случае благодарю за участие, появились некоторые новые мысли. Пока попробую реализовать через указатели.
|
Сообщ.
#11
,
|
|
|
Цитата yourpc @ К сожалению винапи использовать не могу Memo.SetTextBuf(nil) ? |
Сообщ.
#12
,
|
|
|
Memo.SetTextBuf(nil) - никак не влияет на кол-во потребляемой памяти. Тестировал правдо через таскмэнеджер в вин7, потом еще через другие утилиты погляжу, но чисто визуально все также как и :=''
|