Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Быстрая замена символа / 25 сообщений из 259, страница 1 из 11
19.07.2018, 14:14
    #39676186
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Может, кто подскажет, как ещё быстрее можно...

Начал с такого
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function FastCommatopoint(s: string): string;
var
  i: Integer;
begin
  Result := s;
  for i := 1 to Length(s) do
    if Result[i] = ',' then
      Result[i] := '.';
end;



Сейчас дошёл до такого
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
function UseRepneScasb(s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
begin
  Result := s;

  asm
    Push  ESI
    Push  EBX

    Mov   EAX,Result

    Mov EDI, [EAX]
    Mov   ECX,[EDI-4]
    Sub ECX, 1

    Mov   AL,COMMA_
    Mov   BL,DOT_

    Cld
@Next:
    repne scasb
    jecxz @Exit
    Mov   [EDI-1],BL
    Jmp   @Next

@Exit:
    Pop  EBX
    Pop  ESI

  end;
end;



Разница
...
Рейтинг: 0 / 0
19.07.2018, 14:16
    #39676191
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
2 секунды - это такие длинные строки или в цикле?
...
Рейтинг: 0 / 0
19.07.2018, 14:20
    #39676196
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
wadman2 секунды - это такие длинные строки или в цикле?

Строки - 250 Char
ии 10 млн раз ...
...
Рейтинг: 0 / 0
19.07.2018, 14:21
    #39676197
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
zinpubwadman2 секунды - это такие длинные строки или в цикле?

Строки - 250 Char
ии 10 млн раз ...
Лучшеб код сравнения, чем словесное описание. Тут все, конечно, джентльмены, но... :)
...
Рейтинг: 0 / 0
19.07.2018, 14:29
    #39676203
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
А так?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure FastCommatopoint(var s: string);
var
  i: Integer;
begin
  for i := 1 to Length(s) do
    if s[i] = ',' then
      s[i] := '.';
end;
...
Рейтинг: 0 / 0
19.07.2018, 14:30
    #39676204
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
wadman,
...
Рейтинг: 0 / 0
19.07.2018, 14:35
    #39676211
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
zinpub,

DevEx специально используете?
...
Рейтинг: 0 / 0
19.07.2018, 14:35
    #39676212
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure ReplaceChar(const Source, Target: Char; var Str: string);
var
  P: PChar;
  I:Integer;
begin
  Result := Str;
  P := Pointer(Result);
  for i := 0 to Length(Str) - 1 do
  begin
    if P^ = Source then
      P^ := Target;
    Inc(P);
  end;
end;


Сильно отличается от asm варианта?
...
Рейтинг: 0 / 0
19.07.2018, 14:36
    #39676213
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
_Vasilisk_А так?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure FastCommatopoint(var s: string);
var
  i: Integer;
begin
  for i := 1 to Length(s) do
    if s[i] = ',' then
      s[i] := '.';
end;



Так хорошо, но копирование снаружи тогда возникает...
...
Рейтинг: 0 / 0
19.07.2018, 14:38
    #39676215
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Василий 2
Код: pascal
1.
2.
3.
4.
5.
6.
procedure ReplaceChar(const Source, Target: Char; var Str: string);
var
  P: PChar;
  I:Integer;
begin
  Result := Str;
...
Рейтинг: 0 / 0
19.07.2018, 14:44
    #39676221
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Василий 2
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure ReplaceChar(const Source, Target: Char; var Str: string);
var
  P: PChar;
  I:Integer;
begin
  Result := Str;
  P := Pointer(Result);
  for i := 0 to Length(Str) - 1 do
  begin
    if P^ = Source then
      P^ := Target;
    Inc(P);
  end;
end;


Сильно отличается от asm варианта?

Кстати да, тоже хорошо!
...
Рейтинг: 0 / 0
19.07.2018, 14:45
    #39676223
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
zinpub,

авторrepne scasb

у тебя там ansi строки?
...
Рейтинг: 0 / 0
19.07.2018, 14:47
    #39676230
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
makhaon,
Ага, delphi5
...
Рейтинг: 0 / 0
19.07.2018, 14:50
    #39676234
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
_Vasilisk_zinpub,

DevEx специально используете?

А что с ним не так?
...
Рейтинг: 0 / 0
19.07.2018, 14:53
    #39676236
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
zinpub_Vasilisk_zinpub,

DevEx специально используете?

А что с ним не так?

Понял, пардон, кидал на форму, что под рукой было.
...
Рейтинг: 0 / 0
19.07.2018, 17:21
    #39676374
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Василий 2
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure ReplaceChar(const Source, Target: Char; var Str: string);
var
  P: PChar;
  I:Integer;
begin
  Result := Str;
  P := Pointer(Result);
  for i := 0 to Length(Str) - 1 do
  begin
    if P^ = Source then
      P^ := Target;
    Inc(P);
  end;
end;


Сильно отличается от asm варианта?

Фи
Код: pascal
1.
2.
3.
4.
5.
6.
 while P^ <> nil do 
  begin
    if P^ = Source then
        P^ := Target;
     Inc(P);
  end;
...
Рейтинг: 0 / 0
19.07.2018, 17:24
    #39676380
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Гирлионайльдо
Код: pascal
1.
 while P^ <> nil do 


А если никогда не будет?
...
Рейтинг: 0 / 0
19.07.2018, 17:31
    #39676384
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
wadmanА если никогда не будет?Видимо имелось ввиду:
Код: pascal
1.
while P^ <> #0 do 

правда это не сработает в случае строк, которые могут содержать бинарный ноль
...
Рейтинг: 0 / 0
19.07.2018, 17:37
    #39676389
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
На данный момент, самый быстрый вариант такой

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
function ReplaceCharByPChar(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: PChar;
  I: Integer;
begin
  Result := s;
  P := Pointer(Result);
  for i := 0 to Length(s) - 1 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;



Использование while - ускорения не даёт, и чуть замедляет...
...
Рейтинг: 0 / 0
19.07.2018, 17:43
    #39676396
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
zinpubИспользование while - ускорения не даёт, и чуть замедляет
ну понятно. нативный loop и должен быть быстрее велосипедного, иначе зачем он нужен.
...
Рейтинг: 0 / 0
19.07.2018, 18:04
    #39676409
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Да. Там #0 (Прироста нету... Странно ведь!)


Сделал тест на токио. С включённой оптимизацией

Результаты
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
------------------------------------------------------
ForkReplaceC_lodsw   -> 00:00:211
ReplaceCharByPChar   -> 00:00:208
TestMy               -> 00:00:207
------------------------------------------------------
ForkReplaceC_lodsw   -> 00:00:212
ReplaceCharByPChar   -> 00:00:207
TestMy               -> 00:00:208
------------------------------------------------------
ForkReplaceC_lodsw   -> 00:00:220
ReplaceCharByPChar   -> 00:00:213
TestMy               -> 00:00:218
------------------------------------------------------
ForkReplaceC_lodsw   -> 00:00:211
ReplaceCharByPChar   -> 00:00:210
TestMy               -> 00:00:208
------------------------------------------------------
ForkReplaceC_lodsw   -> 00:00:212
ReplaceCharByPChar   -> 00:00:212
TestMy               -> 00:00:212




Код
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TCommatFunc = function(s: string): string;

  TForm1 = class(TForm)
    btnCommaToPoint: TButton;
    mmo1: TMemo;
    mmo2: TMemo;
    btnFill: TButton;
    procedure btnCommaToPointClick(Sender: TObject);
    procedure btnFillClick(Sender: TObject);
  private
    function RunFunc(Func: TCommatFunc): TDateTime;

    procedure FillRandomText(const iFactor, iCharCount: Integer);
    { Private declarations }
  public
    { Public declarations }
  end;

const
  CNT_RUN = 1000000;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function ForkReplaceC_lodsw(s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
begin
  Result := s;

  asm
    Push  ESI
    Push  EBX

    Mov   EAX,Result
    Or    EAX,EAX
    Jz    @Exit
    Mov   ESI,[EAX]
    Or    ESI,ESI
    Jz    @Exit

    Mov   BH,COMMA_
    Mov   BL,DOT_
    Cmp   AH,BL
    Jz    @Exit

    Mov   ECX,[ESI-4]
    Jecxz @Exit
    push ECX

    shr ECX,1

    Cld
  @Next:
    Lodsw
    Cmp   AH,BH
    Jne   @Skip1
    Mov   [ESI-1],BL
  @Skip1:
    Cmp   AL,BH
    Jne   @Skip
    Mov   [ESI-2],BL
  @Skip:
    Dec   ECX
    Jnz   @Next

    // ------------------------
    pop ECX
    and ECX,2
    jz @Exit
  @Next20:
    Lodsb
    Cmp   AH,BH
    Jne   @Skip20
    Mov   [ESI-1],BL
  @Skip20:
    Dec   ECX
    Jnz   @Next20
  @Exit:
    Pop  EBX
    Pop  ESI

  end;
end;

function ReplaceCharByPChar(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: PChar;
  i: Integer;
begin
  Result := s;
  P := Pointer(Result);
  for i := 0 to Length(s) - 1 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function TestMy(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: PChar;
begin
  Result := s;
  P := Pointer(Result);
  while P^ <> #0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

procedure TForm1.btnCommaToPointClick(Sender: TObject);

  function FormatOutput(const aFuncName: string;
    const iRunTime: TDateTime): string;
  begin
    Result := Format('%-20s -> %s', [aFuncName, FormatDateTime('NN:SS:ZZZ',
      iRunTime)]);
  end;

begin
  mmo1.Lines.Add('------------------------------------------------------');

  mmo1.Lines.Add(FormatOutput('ForkReplaceC_lodsw',
    RunFunc(@ForkReplaceC_lodsw)));

  mmo1.Lines.Add(FormatOutput('ReplaceCharByPChar',
    RunFunc(@ReplaceCharByPChar)));

  mmo1.Lines.Add(FormatOutput('TestMy', RunFunc(@TestMy)));

end;

function TForm1.RunFunc(Func: TCommatFunc): TDateTime;
var
  aStartTime: TDateTime;
  i: Integer;
  s: string;
begin
  s := mmo2.Text;

  aStartTime := Now;

  for i := 0 to 50000 - 1 do
    Func(s);

  Result := Now - aStartTime;
end;

procedure TForm1.FillRandomText(const iFactor, iCharCount: Integer);
var
  i: Integer;
  s: string;
begin
  s := '';

  for i := 0 to iCharCount do
  begin
    if Random(10) > iFactor then
      s := s + ','
    else
      s := s + Chr(40 + Trunc(Random(150)));
  end;

  mmo2.Text := s;

end;

procedure TForm1.btnFillClick(Sender: TObject);
begin
  FillRandomText(10, 5000);
end;

end.

...
Рейтинг: 0 / 0
19.07.2018, 18:05
    #39676411
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Вносил правки. И изменил на

Код: pascal
1.
2.
 for i := 0 to 50000 - 1 do
    Func(s);



а так же
Код: pascal
1.
  FillRandomText(10, 5000);
...
Рейтинг: 0 / 0
19.07.2018, 18:10
    #39676414
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
ГирлионайльдоВносил правки. И изменил на

Код: pascal
1.
2.
 for i := 0 to 50000 - 1 do
    Func(s);



а так же
Код: pascal
1.
  FillRandomText(10, 5000);



Factor =10, в FillRandom... Не проставит запятые
...
Рейтинг: 0 / 0
19.07.2018, 18:12
    #39676415
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
_Vasilisk_Василий 2
Код: pascal
1.
2.
3.
4.
5.
6.
procedure ReplaceChar(const Source, Target: Char; var Str: string);
var
  P: PChar;
  I:Integer;
begin
  Result := Str;


Переделывал из кода, где возвращается копия с замененными символами, остался артефакт
...
Рейтинг: 0 / 0
19.07.2018, 18:19
    #39676423
zinpub
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Быстрая замена символа
Василий 2_Vasilisk_пропущено...

Переделывал из кода, где возвращается копия с замененными символами, остался артефакт

Я её допеределывал, чуууть медленнее асма
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Быстрая замена символа / 25 сообщений из 259, страница 1 из 11
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]