![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
заранее задать размер строки Setlength ?
Den © (2012-04-08 00:21:00)задача: ускорить выполнение кода.
есть 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 перезаписываться в другое место в памяти если ей начать присваивать какие-то значения?
Den (2012-04-09 11:27:00) [1]Ну я в нее ем:)
oldman (2012-04-09 10:25:00) [2]
> а потом присвоить значение
> s1:='';
> это обнулит ее length или нет?
МАМА!!! РОДИ МЕНЯ ОБРАТНО!!!
Извините за грубость, но голова на что?
Den (2012-04-09 08:51:00) [3]MBo Спасибо!
MBo (2012-04-09 08:46:00) [4]
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:39:00) [5]маленькое уточнение не суть конечно но всетаки
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;
Den (2012-04-09 08:32:00) [6]Так наверное можно:
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 07:48:00) [7]
> 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 07:10:00) [8]О вспомнил про ветку, заглянул. Спасибо всем кто ответил!
Sha (2012-04-08 18:25:00) [9]> 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
sniknik (2012-04-08 18:00:00) [10]в общем, почему какие то "извращения" с мутными приведением типва к интеджеру, дают лучший код чем явные индексации в массиве/указатели... ведь по смыслу делают то же самое.
sniknik (2012-04-08 17:56:00) [11]а так?
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;
Sha (2012-04-08 17:42:00) [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
Sha (2012-04-08 17:27:00) [13]Конечно, [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],
и работать, наверно, быстрее будет )
sniknik (2012-04-08 16:33:00) [14]> 1. ответ, как всегда, можно посмотреть в CPU window
по количеству ассемблерных операций? у тебя в первом "блоке" присвоении 4, у меня 3, во втором у тебя одна у меня 2. т.е. то на то. но у меня все регистровые у тебя вторая с переменными (что по моему ИМХО, не очень хорошо для оптимальности)
т.что не увидел я там ответа. а код у меня (опять ИМХО) понятнее/короче.
> 2. не, ну я бы еще оптимальнее запутал ) а потом еще раз )
это я бы тоже по другому написал... чисто с эстетической точки зрения.
Sha (2012-04-08 15:52:00) [15]> 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 15:32:00) [16]а это точно "Микрооптимизация"? а не запутывание кода?
более понятное (ИМХО), оно чем то отличается?
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;
MBo (2012-04-08 13:45:00) [17]>Sha
так и знал, что ты не утерпишь, если заглянешь ;)
Sha (2012-04-08 13:26:00) [18]Микрооптимизация, о которой говорил 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 07:13:00) [19]Радикальное ускорение будет, если избавиться от перевыделения пямяти для обеихстрок
Setlength(s1, Length(s) * 2);
for i := 1 to Length(s) do begin
s1[2 * i - 1] :=s[i];
s1[2 * i] := 'a';
end;
Кроме того, еще останется возможность микрооптимизации (понадобится нечасто)
Den (2012-04-08 02:05:00) [20]
> Вот тут давеча на королевстве обсуждали:
> http://www.delphikingdom.com/asp/answer.asp?IDAnswer=80799
Понял, короче быстро не получиться, придется таки разбирать че там к чему. Спасибо.