Форум: "Начинающим";
Текущий архив: 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) а ниже код создает именно описанные проблемы!
и внимение(!) отличается от предыдущего только неиспользуемой переменной sprocedure 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