![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как сократить время выполнения процедуры? [D7, XP]
Tatiana © (2006-02-04 21:59:00)Необходимо прочитать данные из *.txt файла. Данные структурированы. Проблема в том, что если количество строк большое (больше 10 000), то файл открывается недостаточно быстро. Каккие могут быть варианты, чтобы процедура выполнялась быстрее?
Defunct (2006-02-09 22:05:00) [1]> Можно мне мааааленький вопросик? :) Получается, что при выборе варианта чтения данных из файла, единственно возможным становится List.LoadFromFile?
Я бы не говорил так строго, скорее - предпочтительным вариантом, а не единственно возможным.. :)
Потому что размер массива можно также увеличивать постепенно, но не на один элемент, а скажем сразу на 1000 или более (посмотрите реализацию TList).
Tatiana (2006-02-09 21:06:00) [2]
> Думаю стоит задавать длину однократно. Вы точно знаете сколько
> строк прочитано сразу после загрузки файла в List. Вот и
> задайте массиву количество строк в качестве размера, перед
> заполением элементов.
Можно мне мааааленький вопросик? :) Получается, что при выборе варианта чтения данных из файла, единственно возможным становится List.LoadFromFile?
Defunct (2006-02-09 18:14:00) [3]хорошо наверное когда повод для смеха так легко найти? :)
> Потому что про ускорение работы написано именно в строке с with.
а <--- стоИт именно в строке с for, окошко-то для редактирования в форуме до сих пор маленькое.
ладно, в общем у нас как всегда нашелся повод для offtop'а.
begin...end (2006-02-09 17:55:00) [4]> Defunct © (09.02.06 17:47) [39]
> А если тоже самое прочесть не отрывая от следующего коментария,
> тоже будет смешно?
Да, тоже будет. Потому что про ускорение работы написано именно в строке с with. Значит, этот комментарий относится, по крайней мере, и к with тоже (если не только к нему). А это, как уже говорилось, смешно.
Defunct (2006-02-09 17:47:00) [5]> Уфф, как сложно всё...
> Действительно, верится с трудом.
> :о)
Ну так, на самом деле так и есть :)
>> И это послужило поводом для LOL? над коментарием???
> Конечно. Мне действительно было смешно, потому что ускорению работы кода за счёт with здесь просто неоткуда взяться.
А если тоже самое прочесть не отрывая от следующего коментария, тоже будет смешно?
Что-то я не понимаю, проблему автора вопроса я локализовал, что еще от меня требуется? И почему я должен выслушивать насмешки?
begin...end (2006-02-09 17:41:00) [6]> Defunct © (09.02.06 17:27) [37]
> А почему ж тогда написал: "Без очистки не получится, т.к.
> при изменении DelimitedText вызывается Clear."
Потому что без очистки действительно не получится.
> Оба замечания - несущественные, и на скорость практически
> не влияют
ОК, с этим могу согласиться. Но всё же, если сравнивать первое и второе замечания, первое действительно существеннее.
> просто написав первое замечание, искал второе более существенное,
> но так и не найдя, забыл исправить слово "существенное"
> на "несущественное".
Уфф, как сложно всё...
Действительно, верится с трудом.
:о)
> И это послужило поводом для LOL? над коментарием???
Конечно. Мне действительно было смешно, потому что ускорению работы кода за счёт with здесь просто неоткуда взяться.
Defunct (2006-02-09 17:27:00) [7]> Я читал.
А почему ж тогда написал: "Без очистки не получится, т.к. при изменении DelimitedText вызывается Clear."
>Только не понял, почему это было названо "существенным замечанием", а замена while на for -- "несущественным". Потому что на самом деле всё наоборот.
Если скажу честно, то все равно ведь не поверишь, и в очередной раз напишешь дурацкий lol. Оба замечания - несущественные, и на скорость практически не влияют, просто написав первое замечание, искал второе более существенное, но так и не найдя, забыл исправить слово "существенное" на "несущественное".
Фирштейн?
> По крайней мере, в данном случае он не получится более эффективным.
И это послужило поводом для LOL? над коментарием???
begin...end (2006-02-09 17:00:00) [8]> Defunct © (09.02.06 15:25) [33]
> Вдумчиво вчитайся в то, что было мной выброшено из кода.
> А именно был выброшен Clear.
Я читал. Только не понял, почему это было названо "существенным замечанием", а замена while на for -- "несущественным". Потому что на самом деле всё наоборот.
> с with генерируемый код получается более эффективным
По крайней мере, в данном случае он не получится более эффективным.
> PS: что я и говорил ранее - желание "подклоть" так и прет.
LOL. 3 раза.
Defunct (2006-02-09 16:01:00) [9]Gero © (09.02.06 15:53) [34]
Я о "LOL" и о первом предложении.
в том что begin...end дал верный ответ насчет SetDelimitedTest я не сомневаюсь, однако опять же тон каким этот ответ.
Gero (2006-02-09 15:53:00) [10]> > Разгадка -- в коде TStrings.SetDelimitedText, вестимо.
> что ж спасибо, хорошо, что всегда найдутся начитанные люди.
>
> PS: что я и говорил ранее - желание "подклоть" так и прет.
Ты о чем? begin..end дал вполне конкретное объяснение, разгадка действительно в TStrings.SetDelimitedText.
Defunct (2006-02-09 15:25:00) [11]begin...end © (09.02.06 13:10) [32]
> Без очистки не получится, т.к. при изменении DelimitedText вызывается Clear.
Вдумчиво вчитайся в то, что было мной выброшено из кода. А именно был выброшен Clear.
>> with List do // для ускорения работы
> LOL
по словам Digitman, с with генерируемый код получается более эффективным. К тому же коментарий относится также и к for.
> Разгадка -- в коде TStrings.SetDelimitedText, вестимо.
что ж спасибо, хорошо, что всегда найдутся начитанные люди.
PS: что я и говорил ранее - желание "подклоть" так и прет.
begin...end (2006-02-09 13:10:00) [12]> Defunct © (09.02.06 03:59) [25]
> просто менять DelimitedText (без очистки содержимого)
Без очистки не получится, т.к. при изменении DelimitedText вызывается Clear.
> with List do // для ускорения работы
LOL
> Defunct © (09.02.06 12:54) [31]
> Почему? delimiter по-умолчанию не инициализируется значением ' '.
with TStringList.Create do
try
DelimitedText := 'abc def';
ShowMessage(IntToStr(Count))
finally
Free
end
Разгадка -- в коде TStrings.SetDelimitedText, вестимо.
Defunct (2006-02-09 12:54:00) [13]Gero © (09.02.06 11:14) [28]
Почему? delimiter по-умолчанию не инициализируется значением ' '.
Tatiana (09.02.06 11:54) [30]
> SetLength(FPointsArr, MCount + 1);
Вот здесь и тормоза. Изменение размера не маленького массива очень ресурсоемкая операция.
Думаю стоит задавать длину однократно. Вы точно знаете сколько строк прочитано сразу после загрузки файла в List. Вот и задайте массиву количество строк в качестве размера, перед заполением элементов. Далее просто считайте количество добавленных (реальных) элементов. После добавления всех элементов в массив - подкорректируйте его размер - подставьте в SetLength количество подсчитанных элементов.
Tatiana (2006-02-09 11:54:00) [14]
> Defunct © (09.02.06 03:59)
Вот это да!!! Действительно на AddPoint тратится все время....
procedure TPoints.AddPoint(Point: RPoint);
{существует класс, одним из полей является одномерный массив FPoints Arr, функция MCount текущую длину этого массива}
begin
SetLength(FPointsArr, MCount + 1);
FPointsArr[High(FPointsArr)] := Point;
end;
Leonid Troyanovsky (2006-02-09 11:40:00) [15]
> Tatiana (09.02.06 00:21) [24]
> {до этого места все идет достаточно быстро, а вот на нижеследующий
> цикл тратится слишком много времени. Может быть, я преувеличиваю,
> но если в *.txt файле около 17 000 строк (912KB), то программа
> его обрабатывает 5 минут. Ожидание кажется бесконечным..
Подобные файлы на моем Celeron 2GHz 248M of RAM обрабатываются за 0.5 с
(файл 26М - 12 сек, 53М - 25 сек, 107М- 50 сек).
uses
Classes;
procedure TForm1.Button1Click(Sender: TObject);
var
fs: TFileStream;
p: TParser;
sl : Longint;
i: Longint;
f: array [0..2] of Extended;
n, s: String;
t : Cardinal;
begin
t := GetTickCount;
fx := 0;
fs := TFileStream.Create('file1.txt', fmOpenRead);
p := TParser.Create(fs);
while p.Token <> toEOF do
begin
sl := p.SourceLine;
if (p.Token = toSymbol) then // если имя - идентификатор паскаля
begin
n := p.TokenString;
s := '';
for i := 0 to 2 do
begin
p.NextToken;
p.CheckToken(toFloat); // если все числа в формате Float (with '.')
{см. также toInteger}
f[i] := p.TokenFloat;
end;
p.NextToken; // формируем Description
while (p.SourceLine = sl) and (p.Token <> toEOF) do
begin
s := s + ' ' + p.TokenString;
p.NextToken;
end;
{здесь записываем (обрабатываем) полученные значения}
end
else
p.NextToken;
end;
p.Free;
fs.Free;
ShowMessage(Format('%d',[GetTickCount-t]));
end;
Работа над ошибками оставлена в качестве домашнего задания.
--
Regards, LVT.
Gero (2006-02-09 11:14:00) [16]> myStrings.Delimiter := ' '; // <- единожды задать разделитель
Это лишнее.
Tatiana (2006-02-09 11:11:00) [17]
> А тебе очень важно хранить данные именно в *.txt файле.
Лично мне все равно, но не я выбираю :(
vovnuke (2006-02-09 09:39:00) [18]2Tatiana
А тебе очень важно хранить данные именно в *.txt файле.
То работай со своими данными с использованием ClientDataSet, с ним будешь работать как с таблицей базы данных, сохраненной в файле.
Я думаю что загрузить из таблицы 17000 записей, будет побыстрее, чем из текстового файла 17000 строк.
Defunct (2006-02-09 03:59:00) [19]Tatiana (09.02.06 00:21) [24]
несущественное замечание: вместо while лучше использовать for.
существенное замечание: вместо SplitString для ускорения работы лучше единожды задать delimiter для myStrings, и просто менять DelimitedText (без очистки содержимого):
myStrings := TStringList.Create;
myStrings.Delimiter := ' '; // <- единожды задать разделитель
...
with List do // для ускорения работы
for i := 0 to Count - 1 do // <-- вместо while
begin
/// myStrings.Clear; Выбросить
/// SplitString(..); Выбросить
S := Strings[i];
if S <> '' then
begin
myStrings.DelimitedText := S;
...
AddPoint(..); // ВНЕСТИ В ТЕЛО IF (иначе у вас некоторые записи будут дублироваться)
end
end
А также неплохо было бы привести код AddPoint,
для теста попробуйте вначале вообще ее (AddPoint) закоментировать.
Tatiana (2006-02-09 00:21:00) [20]Проблема не в скачивании в память - это происходит быстро, а в разбиении строк.
procedure TPoints.ReadPoints(aFileName: String);
{ñ÷èòûâàåò äàííûå èç ôàéëà ñ èìåíåì aFileName â FStartPointsArr}
var
i : integer;
s : String;
Point: RPoint;
List: TStringList;
myStrings : TStringList;
begin
try
List := TStringList.Create;
myStrings := TStringList.Create;
List.LoadFromFile(aFileName);
i := 0;
While i