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

Вниз

заранее задать размер строки Setlength ?   Найти похожие ветки 

 
Den   (2012-04-08 00:21) [0]

задача: ускорить выполнение кода.
есть 2 переменные s, s1:string; заранее известно что length(s1) не будет больше length(s)*2.

ну и собственно код:

while length(s)>0 do begin
s1:=s1+copy(s, 1,1)+"a";
delete(s,1,1);
end;

если заранее задать размер s1 вот так
setlength(s1, length(s)*2);
а потом присвоить значение
s1:="";
это обнулит ее length или нет? То есть будет ли s1 перезаписываться в другое место в памяти если ей начать присваивать какие-то значения?


 
Германн ©   (2012-04-08 01:18) [1]


> это обнулит ее length или нет? То есть будет ли s1 перезаписываться
> в другое место в памяти если ей начать присваивать какие-
> то значения?
>

1. Обнулит.
2. Считай что будет. Исключения возможны, но не обязательны.

Задачу озвучь, а не вопрос.


 
Германн ©   (2012-04-08 01:22) [2]

P.S.
Вот тут давеча на королевстве обсуждали:
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=80799


 
Den   (2012-04-08 02:03) [3]


> Задачу озвучь, а не вопрос.


Да какая задача постоянно то там то там приходиться обрабатывать кучу строк мысли по поводу того как это ускорить навеяны вот этой статьей, http://www.delphimaster.ru/articles/dyntable/index.html

var
 s: string; //ansistring
 ch: char;
 i, N: integer;
begin
1.  S:= "";
2. for i := 1 to N do
3.    s := s + ch;
...

Первая строка - на самом деле S := nil, довольно просто. А вот третья раскладывается на выделение памяти для новой строки длины (Length(S) + 1) и копирование прежней строки в новую область памяти, после этого S указывает на эту область. И так N раз! На самом деле, в цикле еще идет вызов UniqueString, что тоже не добавляет скорости. И если выделение области памяти сравнительно быстрая операция, то время копирования прежней строки на новое место напрямую зависит от ее длины. Можно показать, что время выполнения строк 2 и 3 пропорционально N^2.


Вот и думаю как ускорить обработку строк, чтоб посмотреть хотябы насколько оно быстрее работать будет.


 
Den   (2012-04-08 02:05) [4]


> Вот тут давеча на королевстве обсуждали:
> http://www.delphikingdom.com/asp/answer.asp?IDAnswer=80799

Понял, короче быстро не получиться, придется таки разбирать че там к чему. Спасибо.


 
MBo ©   (2012-04-08 07:13) [5]

Радикальное ускорение будет, если избавиться от перевыделения пямяти для обеих строк


Setlength(s1, Length(s) * 2);
for i := 1 to Length(s) do begin
 s1[2 * i - 1] :=s[i];
 s1[2 * i] := "a";
end;


Кроме того, еще останется возможность микрооптимизации (понадобится нечасто)


 
Sha ©   (2012-04-08 13:26) [6]

Микрооптимизация, о которой говорил MBo ©   (08.04.12 07:13) [5]


function Split(const s: AnsiString): AnsiString;
var
 t, i: integer;
begin;
 SetString(Result, nil, 2*Length(s));
 t:=integer(Result); //IA-32
 for i:=0 to Length(s)-1 do begin;
   pchar(t)[0]:=s[i+1];
   pchar(t)[1]:=",";
   inc(t,2);
   end;
 end;

procedure TForm1.Button1Click(Sender: TObject);
begin;
 ShowMessage(Split("abc"));
 end;


 
MBo ©   (2012-04-08 13:45) [7]

>Sha
так и знал, что ты не утерпишь, если заглянешь ;)


 
sniknik ©   (2012-04-08 15:32) [8]

а это точно "Микрооптимизация"? а не запутывание кода?

более понятное (ИМХО), оно чем то отличается?
 function Split(const s: AnsiString): AnsiString;
 var
   i: integer;
   p: PAnsiChar;
 begin;
   SetLength(result, Length(s)*2);
   p:= PAnsiChar(result);
   for i:= 1 to Length(s) do begin
     p[0]:= s[i];
     p[1]:= ",";
     Inc(p, 2);
   end;
   SetLength(result, Length(result)-1);
 end;


 
Sha ©   (2012-04-08 15:52) [9]

> sniknik ©   (08.04.12 15:32) [8]
> а это точно "Микрооптимизация"? а не запутывание кода?

У меня сразу два ответа
1. ответ, как всегда, можно посмотреть в CPU window
2. не, ну я бы еще оптимальнее запутал ) а потом еще раз )


function Split(const s: AnsiString): AnsiString;
var
 t: pWordArray;
 i, ch: integer;
begin;
 i:=Length(s);
 SetString(Result, nil, 2*i);
 integer(t):=integer(Result); //IA-32 only
 while i>0 do begin;
   ch:=Ord(s[i]);
   dec(i);
   ch:=ch or (Ord(AnsiChar(",")) shl 8);
   t[i]:=ch;
   end;
 end;


 
sniknik ©   (2012-04-08 16:33) [10]

> 1. ответ, как всегда, можно посмотреть в CPU window
по количеству ассемблерных операций? у тебя в первом "блоке" присвоении 4, у меня 3, во втором у тебя одна у меня 2. т.е. то на то. но у меня все регистровые у тебя вторая с переменными (что по моему ИМХО, не очень хорошо для оптимальности)
т.что не увидел я там ответа. а код у меня (опять ИМХО) понятнее/короче.

> 2. не, ну я бы еще оптимальнее запутал ) а потом еще раз )
это я бы тоже по другому написал... чисто с эстетической точки зрения.


 
Sha ©   (2012-04-08 17:27) [11]

Конечно, [6] - просто демонстрация идеи.
Если говорить об эстетике, то ее можно переписать, например, так

type
 PData= ^TData;
 TData= packed record
   ch: AnsiChar;
   comma: AnsiChar;
   end;
 PDataArray= ^TDataArray;
 TDataArray= array[0..0] of TData;

function Split(const s: AnsiString): AnsiString;
var
 p: PDataArray;
 i: integer;
begin;
 i:=Length(s);
 SetString(Result, nil, 2*i);
 integer(p):=integer(Result); //IA-32 only
 while i>0 do begin;
   dec(i);
   p[i].ch:=s[i+1];
   p[i].comma:=",";
   end;
 end;


При этом и те красота,
и длина цикла будет на 6 байтов меньше, чем [8],
и работать, наверно, быстрее будет )


 
Sha ©   (2012-04-08 17:42) [12]

> sniknik ©   (08.04.12 16:33) [10]
> по количеству ассемблерных операций?

нет, по качеству:

     p[0]:= s[i];
004529B2 8A4C13FF         mov cl,[ebx+edx-$01]
004529B6 8B2F             mov ebp,[edi]         <-- это плохой, негодный оператор )
004529B8 884D00           mov [ebp+$00],cl
     p[1]:= ",";
004529BB 8B0F             mov ecx,[edi]         <-- это тоже плохой, негодный оператор )
004529BD C641012C         mov byte ptr [ecx+$01],$2c


 
sniknik ©   (2012-04-08 17:56) [13]

а так?
 function Split2(const s: AnsiString): AnsiString;
 var
   p: PChar;
   i: integer;
 begin;
   result:= StringOfChar(",", Length(s)*2-1);
   p:= @result[1];
   for i:= 1 to Length(s) do begin
     p^:= s[i];
     Inc(p, 2);
   end;
 end;


 
sniknik ©   (2012-04-08 18:00) [14]

в общем, почему какие то "извращения" с мутными приведением типва к интеджеру, дают лучший код чем явные индексации в массиве/указатели... ведь по смыслу делают то же самое.


 
Sha ©   (2012-04-08 18:25) [15]

> sniknik ©   (08.04.12 17:56) [13]
> а так?

так быстрее тоже не будет,
1. т.к. по массиву пробегаемся 2 раза
2. т.к. индекс элемента хранится в ОП, а не в регистре

004529B2 8A4C13FF         mov cl,[ebx+edx-$01]
004529B6 8B3424           mov esi,[esp]         <-- грузим индекс из ОП
004529B9 880E             mov [esi],cl             <-- используем
004529BB 83042402         add dword ptr [esp],$02  <-- наращиваем индекс в ОП

> sniknik ©   (08.04.12 18:00) [14]
> в общем, почему какие то "извращения"...

тайна сия великая есть, настоящие герои ходят Дорогой непрямой:
http://guildalfa.ru/alsha/node/10


 
Den   (2012-04-09 07:10) [16]

О вспомнил про ветку, заглянул. Спасибо всем кто ответил!


 
Den   (2012-04-09 07:48) [17]


> Setlength(s1, Length(s) * 2);
> for i := 1 to Length(s) do begin
>  s1[2 * i - 1] :=s[i];
>  s1[2 * i] := "a";
> end;


А как добавить к примеру не "a" а допустим "dddddd" ? То есть как сделать чтоб вот так можно было:
for i := 1 to Length(s) do begin
s1[2 * i - 1] :=s[i];
s1[2 * i] := "dddddd";
end;

?


 
Den   (2012-04-09 08:32) [18]

Так наверное можно:
procedure TForm1.Button1Click(Sender: TObject);
var
s,s1,s3:string;
i,i1,i2:integer;
begin
s:="12345";
s3:="ddddd";
setlength(s1,length(s)*length(s3));
i1:=1;
for i:=1 to length(s) do begin
s1[i1]:=s[i];
s1[i1+1]:="d";
for i2:=1 to length(s3) do begin
s1[i1+i2]:=s3[i2];
end;
inc(i1,length(s3));
memo1.lines.Add(s1);
end;
end;

насчет быстродействия чет правда сомневаюсь, надо проверить как-то...


 
Den   (2012-04-09 08:39) [19]

маленькое уточнение не суть конечно но всетаки

procedure TForm1.Button1Click(Sender: TObject);
var
s,s1,s3:string;
i,i1,i2:integer;
begin
s:="12345";
s3:="ddddd";
setlength(s1,length(s)+length(s)*length(s3));
i1:=1;
for i:=1 to length(s) do begin
s1[i1]:=s[i];
s1[i1+1]:="d";
for i2:=1 to length(s3) do begin
s1[i1+i2]:=s3[i2];
end;
inc(i1,length(s3)+1);
memo1.lines.Add(s1);
end;
end;


 
MBo ©   (2012-04-09 08:46) [20]

s := "12345";
 s3 := "ddddd";
 l3 := Length(s3);
 l3p1 := l3 + 1;
 SetLength(s1, Length(s) * l3p1);
 for i := 0 to Length(s) - 1 do begin
   s1[1 + i * l3p1] := s[i + 1];
   Move(s3[1], s1[2 + i * l3p1], l3 * SizeOf(Char));
 end;


 
Den   (2012-04-09 08:51) [21]

MBo Спасибо!


 
oldman ©   (2012-04-09 10:25) [22]


> а потом присвоить значение
> s1:="";
> это обнулит ее length или нет?


МАМА!!! РОДИ МЕНЯ ОБРАТНО!!!
Извините за грубость, но голова на что?


 
Den   (2012-04-09 11:27) [23]

Ну я в нее ем:)



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

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

Наверх




Память: 0.51 MB
Время: 0.078 c
2-1333342741
Екатерина
2012-04-02 08:59
2013.03.22
variant massiv


2-1335086959
leklerk
2012-04-22 13:29
2013.03.22
Событие OnResize формы


2-1329256529
Deltas
2012-02-15 01:55
2013.03.22
Что за... сообщение в Delphi XE2.


15-1330599411
Pit
2012-03-01 14:56
2013.03.22
Импорт интерфейсов из C# в Delphi


15-1339000608
alexdn
2012-06-06 20:36
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский