Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Приложение виснет и потребляет память на win7-x64, при этом все о   Найти похожие ветки 

 
Че   (2012-02-09 17:10) [0]

Приложение виснет и потребляет память на win7-x64, при этом все ок на win-xp x86.

Привет,

Есть приложение,
состоит из формы на которой только одна единственная кнопка, которая вызывает  процедуру readtextfile();

вот код этой процедуры:
procedure readtextfile();
var
f: textfile;
str: string;
i: integer;
begin
i := 0;
AssignFile(f, "C:\somefile.txt");
Reset(f);
while not EOF(f) do begin
   str := "";
   ReadLn(f, str);
   i := i + 1;
   frmMain.Caption := IntToStr(i);
end;
frmMain.Caption := "before close";
CloseFile(f);
frmMain.Caption := "after close";
end;


Этот код читает строки из файла C:\somefile.txt.

В моем случае этот файл содержит 2Млн строк, каждая из которых это символ "0" и перевод каретки,
то есть

0
0
0
0
0
...
(всего таких 2 млн строк)

Я компилировал этот код и в Delphi 6 и в Delphi 7, поведение приложения одинаковое.

Один и тот же exe
В winxp x86 ведет себя так:
1. после нажатия на кнопку бегут цифры в заголовке формы
2. Когда все 2млн строк прочитаны, никаких проблем не происходит

Однако, есть другая проблема EOF может случиться на любом месте, например 16344 строк или 23456.

В win7 x64 ведет себя так:
1. после нажатия на кнопку бегут цифры в заголовке формы
2. Приложение нельзя двигать в другое место экрана,
  можно тыцнуть в любое другое окно,
  но ничего не произойдет, то есть ничего сделать нельзя пока файл читается и бегут цифры. Кроме движения мыши по экрану.
3. Чем больше строк прочитано, тем чуть большие подтормаживания заметны, лаги между чтениями,
  то есть на 1.7 млн движение цифр может чуть зависнуть, потом опять продолжиться.
  В диспетчере задач потребление памяти СИЛЬНО растет, прямая под углом 45 градусов.
4. Когда все 2млн строк прочитаны, все наглухо залипает минут на 3-5. По диспетчеру задачь эта память резко освобождается.

Это что-то известное? Какой-то баг? Как лечится?

Или ошибка в ДНК?


 
Че   (2012-02-09 17:12) [1]

прошу прощения, это

> Однако, есть другая проблема EOF может случиться на любом
> месте, например 16344 строк или 23456.

лишнее


 
Anatoly Podgoretsky ©   (2012-02-09 17:16) [2]

> Че  (09.02.2012 17:10:00)  [0]

Здесь не обрабатываются сообщения.


 
RWolf ©   (2012-02-09 17:20) [3]

а если выкинуть строчку frmMain.Caption := IntToStr(i) ?


 
icWasya ©   (2012-02-09 17:23) [4]

или поставить после
frmMain.Caption := IntToStr(i);

строку
Application.ProcessMessages()


 
Сергей М. ©   (2012-02-09 22:09) [5]


> EOF может случиться на любом месте, например 16344 строк
> или 23456


Это как это так - "может случиться" ?

Типо на x86-систему звезды не влияют и все 2 млн строк вплоть до последней циклом прочитываются, а на x64-системе EOF приключается в любой секунд по чьему-то капризу и цикл прерывается по EOF ? Так что ли ?


 
Че   (2012-02-09 23:45) [6]

Удалено модератором


 
Че   (2012-02-09 23:45) [7]

Удалено модератором
Примечание: Обсуждение модерирования


 
Че   (2012-02-09 23:49) [8]

Разница в уровне памяти (синяя линия на скриншоте) между п.1 и п.2 примерно 1Гб, весь размер физической памяти - 6Гб.

Т.е. просто от чтения 2млн строк он сжирает более 1Гб памяти и почему-то ставит всё колом в это время и особенно когда эту память освобождает.


 
Че   (2012-02-09 23:51) [9]

Может кто-либо проверить этот код на win7 x64 ?


 
Че   (2012-02-10 01:41) [10]


> RWolf ©   (09.02.12 17:20) [3]
> а если выкинуть строчку frmMain.Caption := IntToStr(i) ?
>

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

1) Без этой строки файл читается за секунду и приложение спокойно продолжает жить в Idle state.

2) код ниже абсолютно не создает проблем и не жрет память вообще
procedure readtextfile();
var
 i: integer;
begin
 for i := 1 to 2000000 do begin
   frmMain.Caption := IntToStr(i);
   Application.ProcessMessages();
 end;
end;


3) а ниже код создает именно описанные проблемы!
и внимение(!) отличается от предыдущего только неиспользуемой переменной s
procedure readtextfile();
var
 i: integer;
 s: string;
begin
 i := 0;
 for i := 1 to 2000000 do begin
   frmMain.Caption := IntToStr(i);
   Application.ProcessMessages();
 end;
end;


Выполнение кода из пункта 2) абсолютно адекватное, фокус можно менять на любое окно, все работает отлично.
Выполнение кода из пункта 3) неадекватное, цифры бегут гораздо быстрее, чем в 2).

4) Если в коде (3) убрать
frmMain.Caption := IntToStr(i);
то, код становится безпроблемным.

Все это указывает на какой-то баг в обработке сообщений, связанный, вероятно, с оптимизацией кода.


 
Че   (2012-02-10 01:46) [11]

Если в проблемном коде заменить
 frmMain.Caption := IntToStr(i);
на что-то типа
 frmMain.edit1.text := IntToStr(i);
то тоже проблема уходит.

Вопрос можно закрывать. Моя версия - бага связанная с ошибкой в обработке сообщений, причем в случае, когда именно изменяется caption плюс строковая переменная в процедуре должна быть объявлена.


 
Германн ©   (2012-02-10 02:31) [12]


> причем в случае, когда именно изменяется caption плюс строковая
> переменная в процедуре должна быть объявлена.

Вот отсюда пожалуйста подробнее. Что за "строковая переменная" и где и как она  должна быть объявлена?
В твоих примерах ничего подобного не было!
А может быть просто нужно было выделить этой "строковой переменной" память?


 
Че   (2012-02-10 07:50) [13]


> Вот отсюда пожалуйста подробнее. Что за "строковая переменная"
> и где и как она  должна быть объявлена?

вот код без проблем

> 2) код ниже абсолютно не создает проблем и не жрет память
> вообще
> procedure readtextfile();
> var
>  i: integer;
> begin
>  for i := 1 to 2000000 do begin
>    frmMain.Caption := IntToStr(i);
>    Application.ProcessMessages();
>  end;
> end;


вот код, который ведет себя как было описано (память жрет и т.д.)

> 3) а ниже код создает именно описанные проблемы!
> и внимение(!) отличается от предыдущего только неиспользуемой
> переменной s
> procedure readtextfile();
> var
>  i: integer;
>  s: string;
> begin
>  for i := 1 to 2000000 do begin
>    frmMain.Caption := IntToStr(i);
>    Application.ProcessMessages();
>  end;
> end;


 
И. Павел ©   (2012-02-10 08:07) [14]

> Че

А антивирус какой-нибудь работает? Если да — попробуйте его выключить и запустить программу без него.

Пробовал на Windows XP x64 — код из [0] работает нормально, память не увеличивается.


 
И. Павел ©   (2012-02-10 08:10) [15]

> [14] И. Павел ©   (10.02.12 08:07)

Еще посмотрите — нет ли в системе программ, которые могут «конфликтовать» с вашей. Например, если программа «читает» содержимое чужого окна, может возникать подвисание.
Баг в системе или delphi (если это не XE2, конечно :) стоит подозревать в последнюю очередь.


 
И. Павел ©   (2012-02-10 08:14) [16]

> Например, если программа «читает» содержимое чужого окна,
> может возникать подвисание.

К примеру: замечал такое на EhLib + Abby lingvo, если последний переводит автоматически текст под курсором. Помогает установка перевода по нажатию ctrl.
В общем — проверьте все программы, которые могут взаимодействовать с вашей.


> причем в случае, когда именно изменяется caption плюс строковая
> переменная в процедуре должна быть объявлена.

Оптимизатор кода отключен? Если включен, не думаю, что компилятор включит эту переменную в код — она же нигде не используется.


 
Че   (2012-02-10 08:44) [17]

Странно, точно помню, вчера без строковой переменной проблемы не было, сегодня проблема и без нее проблема воспроизводится, вот таким кодом:
procedure p();
var
i: integer;
begin
for i := 1 to 2000000 do begin
  form1.Caption := IntToStr(i);
  Application.ProcessMessages();
end;
end;



> Оптимизатор кода отключен? Если включен, не думаю, что компилятор
> включит эту переменную в код — она же нигде не используется.
>


Можешь этот код выше попробовать на win7 x64?


 
Че   (2012-02-10 08:51) [18]


> сегодня проблема и без нее проблема воспроизводится, вот
> таким кодом:

Но сегодня оно воспроизводится в гораздо меньшей степени, возможно связано с тем, что все ядра CPU сегодня заняты.
По цифрам видно, что они сначала бегут скачкообразно, потом очередь рассасывается, потом опять резко, потом медленно. Т.е. вроде как очередь успевает разбираться. Предполагаю, что если я освобожу все ядра, не могу сейчас это сделать, то опять все полетит с космической скоростью, но при этом память будет расти и по окончании цикла залипнет на освобождении (или обработке очереди).


 
И. Павел ©   (2012-02-10 09:23) [19]

> Можешь этот код выше попробовать на win7 x64?

Нет, 64 битной семерки у меня нет. Но вечером попробую запустить код на win xp x64.


 
sniknik ©   (2012-02-10 09:32) [20]

Caption изменяется сообщением... т.е. выделяется память под строку значение, адрес передается в сообщении, меняется, память освобождается.
2 миллиона сообщений на одно действие из которых разглядеть можно от силы 2 (первое, и последнее) это как то слишком для любой ситуации не зависимо, есть "глюк" или нет.

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



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.069 c
15-1346515594
Artem
2012-09-01 20:06
2013.03.22
Как передать файл на 2 Мб на древний DOS ноутбук?


15-1350977154
han_malign
2012-10-23 11:25
2013.03.22
Производственный календарь на 2013 г.


15-1338398557
Биос
2012-05-30 21:22
2013.03.22
Три звуковых сигнала из системника.


6-1261335712
Vladimir
2009-12-20 22:01
2013.03.22
Передача записи по сети через сокеты


15-1340305869
Ega23
2012-06-21 23:11
2013.03.22
Знатокам Оракла и вообще.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский