Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как сократить время выполнения процедуры? [D7, XP]


Страницы:   1 2 3

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


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо