powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Быстрая замена символа
25 сообщений из 259, страница 5 из 11
Быстрая замена символа
    #39676915
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоPolesov,

Твоя asm функция капелька в море в производительности
Rep4Bytes -> 00:01:083
UseLodsD -> 00:02:088


У меня получились другие цифры (значения в миллисекундах):
Код: powershell
1.
2.
3.
FastCommatopoint: 1047
UseLodsD: 719
Rep4Bytes: 828


Процессор i7-4790, 3.6 GHz, Win 8.1 x64

Вот тестовый код:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  Memo1.Lines.Clear;
  t := GetTickCount;
  for i := 1 to 10000000 do
    s := FastCommatopoint( z );
  Memo1.Lines.Add( 'FastCommatopoint: ' + IntToStr( GetTickCount - t ) );

  t := GetTickCount;
  for i := 1 to 10000000 do
    s := UseLodsD( z );
  Memo1.Lines.Add( 'UseLodsD: ' + IntToStr( GetTickCount - t ) );

  t := GetTickCount;
  for i := 1 to 10000000 do
    s := Rep4Bytes( z );
  Memo1.Lines.Add( 'Rep4Bytes: ' + IntToStr( GetTickCount - t ) );



функцию UseLodsD можно ускорить процентов на 6-8, если после чтения последовательно сравнивать AL и AH и сдвигать EAX на 16.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676916
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоЗа то она самая быстрая, из всех предложенных вариантов :D И я этим горжусь,,даже на asm никто не осилил быстрее
Она у тебя просто работает некорректно.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676917
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоЗа то она самая быстрая, из всех предложенных вариантов :D И я этим горжусь,,даже на asm никто не осилил быстрее

а то, что она немного портит исходные данные, неважно )
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676947
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин. Я ожидал что компилятор скопирует строку, а он не сделал это. Он делает это только вот так

Код: pascal
1.
2.
  Result := str;
  Result[1] := Result[1];



Иначе Result остаётся указателем на str... Капец подводный камюшек. Весь мизинчик разбил в кровь
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676949
Гирлионайльдо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда мой вариант подходит для того, если заменяемый символ встречается не так часто.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676960
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоТогда мой вариант подходит для того, если заменяемый символ встречается не так часто.
Твой корректный вариант работает чуть быстрее моего, если данные сформированы по условиям TC (По данным : около 2-3 МБ на вход на каждые 10-15 символов ЗПТ). Разница в производительности крайне незначительна и, на мой взгляд, не оправдывает усложнения кода. Но если в каждой четвёрке символов будет запятая твой вариант начинает сильно отставать.

p.s. А ты, случаем, не Няшик?
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676963
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоБлин. Я ожидал что компилятор скопирует строку, а он не сделал это. Он делает это только вот так

Код: pascal
1.
2.
  Result := str;
  Result[1] := Result[1];



Иначе Result остаётся указателем на str... Капец подводный камюшек.

так тоже не так сделает, обломается на пустой строке
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676974
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попкорна уже не хватает.
Предлагаю ТС заняться оптимизацией секций initialization и finalization - вот где поле-то непаханное.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676975
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ГирлионайльдоБлин. Я ожидал что компилятор скопирует строку

Все правильно делает компилятор. Если строка не меняется, зачем нужна ее копия, если можно просто увеличить счетчик ссылок?


ГирлионайльдоОн делает это только вот так

Код: pascal
1.
2.
  Result := str;
  Result[1] := Result[1];



Иначе Result остаётся указателем на str... Капец подводный камюшек.

Покури справку по UniqueString
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676978
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы уж определитесь, что именно делаете - новую строку с заменами или замены в старой строке. ТС-у был нужен второй вариант, как мне кажется. Первый же элементарно получается из второго добавлением UniqueString и возвратом результата. Да и как-то странно говорить о быстроте и выжимать такты, когда всё начинается с жирного выделения и копирования памяти.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676994
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
makhaon1. Многопоточность никак не поможет?
Мне с файлами, бывает, сильно помогает.
2. MMX никак не поможет?
Ну и с объемными данными тоже.

1. Нельзя, он(сервис) и так в 20 потоках пашет,
2. Думаю...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39676995
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PolesovПривет.

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;



Можно читать по 4 байта. У меня получилось примерно в два раза вышеприведенного варианта:

Код: 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.
function UseLodsD( s : AnsiString ) : AnsiString;
begin
  Result := s;

  asm
       Push     ESI
       Push     EDI
       Push     EBX

       Mov      EAX,    Result

       Mov      ESI,    [EAX]
       Mov      ECX,    [ESI - 4]
       Mov      EBX,    ECX
       And      EBX,    011b
       Shr      ECX,    2

  @@10:
       LodsD
       Mov      EDX,    4

  @@20:
       Cmp      AL,     ','
       Jne      @@30
       Mov      EDI,    ESI
       Sub      EDI,    EDX
       Mov      Byte Ptr [EDI], '.'

  @@30:
       Shr      EAX,    8
       Dec      EDX
       Test     EDX,    EDX
       Jnz      @@20

       Loop     @@10

       Test     EBX,    EBX
       Jz       @@90

       Mov      ECX,    EBX

  @@40:
       LodsB
       Cmp      AL,     ','
       Jne      @@50
       Mov      Byte Ptr [ESI - 1], '.'

  @@50:
       Loop    @@40

  @@90:
       Pop      EBX
       Pop      EDI
       Pop      ESI
  end;
end;



С уважением, Poleosv.

Пробовал, почему-то по одному lodsb быстрее, хотя у меня несколько по другому... попробую
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677000
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ГирлионайльдоЯ сделать самую быструю функцию! Кто сможет меня вздёрнуть?) (Только не надо SSE, он точно быстрее будет)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
------------------------------------------------------
ReplaceCharByPChar   -> 00:02:879
TestMy               -> 00:02:368
PEnd                 -> 00:02:797
Rep4Bytes            -> 00:01:084
Самый быстрый: 4     -> 00:01:084
------------------------------------------------------
ReplaceCharByPChar   -> 00:02:945
TestMy               -> 00:02:470
PEnd                 -> 00:02:975
Rep4Bytes            -> 00:01:097
Самый быстрый: 4     -> 00:01:097



Код тестовый
Код: 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.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
unit Unit1;

interface

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

type
  ApChar = AnsiChar;
  ApString = AnsiString;
  ApPChar = PAnsiChar;

  TCommatFunc = function(s: ApString): ApString;

  TForm1 = class(TForm)
    btnCommaToPoint: TButton;
    mmo1: TMemo;
    mmo2: TMemo;
    btnFill: TButton;
    Memo1: TMemo;
    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 = 100000; // РАБОТАЕТ

var
  Form1: TForm1;

implementation

{$R *.DFM}

function ReplaceCharByPChar(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
  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(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
begin
  Result := s;
  P := Pointer(Result);
  while P^ <> #0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function PEnd(s: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P: ApPChar;
  PEnd: Pointer;
begin
  Result := s;
  P := Pointer(Result);
  PEnd := P + Length(s);
  while P < PEnd do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    Inc(P);
  end;
end;

function Rep4Bytes(str: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P, C: ApPChar;
  len: Cardinal;
  Sum: NativeUInt;
  Offset: byte;
  i: Integer;
begin
  Result := str;
  P := Pointer(Result);
  len := Length(str);

  while len >= sizeof(ApPChar) do
  begin
    Sum := PNativeUInt(P)^ xor (72340172838076673 * ord(COMMA_));
    if ((Sum - $01010101) and not Sum and $80808080) <> 0 then
    begin
      for Offset := 0 to 3 do
      begin
        C := ApPChar(P + Offset);
        if C^ = COMMA_ then
          C^ := DOT_;
      end;
    end;
    dec(len, sizeof(ApPChar));
    Inc(P, sizeof(ApPChar));
  end;

  while len <> 0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    dec(len);
    Inc(P);
  end;
end;

var
  MinTest: TDateTime;
  IdxMin, IdxCurr: Integer;

procedure TForm1.btnCommaToPointClick(Sender: TObject);

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

begin
  MinTest := TDateTime(1000000000);
  IdxMin := 0;
  IdxCurr := 0;

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

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

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

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

  mmo1.Lines.Add(FormatOutput('Самый быстрый: ' + (IdxMin + 1).ToString,
    MinTest));

end;

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

  aStartTime := Now;

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

  Result := Now - aStartTime;

  if MinTest - Result > 0 then
  begin
    MinTest := Result;
    IdxMin := IdxCurr;
  end;
  Inc(IdxCurr);
end;

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

  for i := 0 to iCharCount do
  begin
    s := s + ','
  end;

  mmo2.Text := s;

end;

procedure TForm1.btnFillClick(Sender: TObject);
begin
  FillRandomText(20, 10000);
end;

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.
34.
35.
36.
37.
38.
39.
function Rep4Bytes(str: ApString): ApString;
const
  COMMA_ = ',';
  DOT_ = '.';
var
  P, C: ApPChar;
  len: Cardinal;
  Sum: NativeUInt;
  Offset: byte;
  i: Integer;
begin
  Result := str;
  P := Pointer(Result);
  len := Length(str);

  while len >= sizeof(ApPChar) do
  begin
    Sum := PNativeUInt(P)^ xor (72340172838076673 * ord(COMMA_));
    if ((Sum - $01010101) and not Sum and $80808080) <> 0 then
    begin
      for Offset := 0 to 3 do
      begin
        C := ApPChar(P + Offset);
        if C^ = COMMA_ then
          C^ := DOT_;
      end;
    end;
    dec(len, sizeof(ApPChar));
    Inc(P, sizeof(ApPChar));
  end;

  while len <> 0 do
  begin
    if P^ = COMMA_ then
      P^ := DOT_;
    dec(len);
    Inc(P);
  end;
end;



Ноздря в ноздрю с ForkReplaceC

------------------------------------------------------
FastCommaToPoint -> 00:00:906
UseReplaceC -> 00:00:547
ForkReplaceC -> 00:00:187
UseRepneScasb -> 00:00:203
PCharRepl -> 00:00:844
ForkReplaceC_lodsw -> 00:00:250
ReplaceCharByPChar -> 00:00:594
ReplaceCharByPChar_While -> 00:00:640
ForForForFor -> 00:00:578
ReplaceCharByPChar_WhileByLen -> 00:00:657
ReplaceKazantsev4 -> 00:00:406
Rep4Bytes -> 00:00:187
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677001
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksandr Sharahovzinpubпропущено...


Да, косякнул...


вставь между этими операторами
Код: pascal
1.
UniqueString(Result);



и чтобы сразу видеть инвалидные функции в тело RunFunc можно добавить предварительную проверку
Код: pascal
1.
2.
3.
4.
5.
  t:=Func(s);
  if (pos(',',s)=0) or (pos(',',t)<>0) or (t=s) then begin;
   Result:=1;
   exit;
   end



и наконец, в объявление функций лучше добавить const
Код: pascal
1.
  TCommatFunc = function(const s: ApString): ApString;



также можно рассмотреть процедуры
Код: pascal
1.
  TCommaProc = procedure(var s: ApString);



Объявление да исправил....

через var нельзя... там Copy местами передаёт параметр...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677005
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВСЕМ СПАСИБО !!

Остановился на таком варианте...

Код: 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.
function ForkReplaceC(const s: string): string;
const
  COMMA_ = ',';
  DOT_ = '.';
begin
  Result := s;
  UniqueString(Result);

  asm
    Push  ESI
    Push  EBX

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

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

    Mov   ECX,[ESI-4]
    Jecxz @Exit

    Cld
@Next:
    Lodsb
    Cmp   AL,AH
    Jne   @Skip
    Mov   [ESI-1],BL
@Skip:
    Dec   ECX
    Jnz   @Next
@Exit:
    Pop  EBX
    Pop  ESI
  end;
end;
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677006
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub,

авторНельзя, он(сервис) и так в 20 потоках пашет,

даже у нас на одной тествой машине 10ти летней давности с двумя ядрами сотня потоков работает без особых проблем. в том числе как раз файлы гигабайтами перемалывает.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677008
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
makhaonzinpub,

авторНельзя, он(сервис) и так в 20 потоках пашет,

даже у нас на одной тествой машине 10ти летней давности с двумя ядрами сотня потоков работает без особых проблем. в том числе как раз файлы гигабайтами перемалывает.

А, что даст сотня потоков, если все ядра разобраны ?

Или, я чего то не понимаю...
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677015
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubmakhaonzinpub,

пропущено...


даже у нас на одной тествой машине 10ти летней давности с двумя ядрами сотня потоков работает без особых проблем. в том числе как раз файлы гигабайтами перемалывает.

А, что даст сотня потоков, если все ядра разобраны ?

Или, я чего то не понимаю...

Сотня потоков даст непрерывную нагрузку на процессор (перемалывает файлы - ждет завершения ввода-вывода)
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677017
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubПробовал, почему-то по одному lodsb быстрее, хотя у меня несколько по другому... попробую

Вот немного улучшенный вариант с чтением по 4 байта (последовательное сравнение AL, AH и сдвигом вправо на 16):
Код: 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.
function UseLodsD2( s : AnsiString ) : AnsiString;
begin
  Result := s;

  asm
       Push     ESI
       Push     EDI
       Push     EBX

       Mov      EAX,    Result

       Mov      ESI,    [EAX]
       Mov      ECX,    [ESI - 4]
       Mov      EBX,    ECX
       And      EBX,    011b
       Shr      ECX,    2

  @@10:
       LodsD
       Mov      EDX,    2

  @@20:
       Cmp      AL,     ','
       Jne      @@25
       Mov      EDI,    ESI
       Sub      EDI,    EDX
       Mov      Byte Ptr [EDI], '.'

  @@25:
       Cmp      AH,     ','
       Jne      @@30
       Mov      EDI,    ESI
       Sub      EDI,    EDX
       Mov      Byte Ptr [EDI], '.'

  @@30:
       Shr      EAX,    16
       Dec      EDX
       Test     EDX,    EDX
       Jnz      @@20

       Loop     @@10

       Test     EBX,    EBX
       Jz       @@90

       Mov      ECX,    EBX

  @@40:
       LodsB
       Cmp      AL,     ','
       Jne      @@50
       Mov      Byte Ptr [ESI - 1], '.'

  @@50:
       Loop    @@40

  @@90:
       Pop      EBX
       Pop      EDI
       Pop      ESI
  end;
end;




Вот вариант с LodsB (простой в реализации):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
function UseLodsB( s : AnsiString ) : AnsiString;
begin
  Result := s;

  asm
       Push     ESI

       Mov      EAX,    Result
       Mov      ESI,    [EAX]
       Mov      ECX,    [ESI - 4]

  @@10:
       LodsB
       Cmp      AL,     ','
       Jne      @@20
       Mov      Byte Ptr [ESI - 1], '.'

  @@20:
       Loop    @@20

       Pop      ESI
  end;
end;




Вот результаты:
Код: powershell
1.
2.
3.
FastCommatopoint: 1047
UseLodsD2: 625
UseLodsB: 735



В принципе, результаты ожидаемы.

P.S. Хотелось бы посмотреть на вариант функции, победившей в этом "тендере" :-)
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677021
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpubВСЕМ СПАСИБО !!
Остановился на таком варианте...


У меня на i7-7700 вот такое быстрее + универсальнее, понятнее, паскальнее )

Код: 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.
var
  CharReplaceTable: array[byte] of byte;

procedure InitCharReplaceTable(const FromChars, ToChars: string; pCharReplaceTable: pByteArray);
var
  i, len: integer;
begin;
  for i:=0 to 255 do pCharReplaceTable[i]:=i;
  i:=Length(FromChars);
  len:=Length(ToChars);
  if len>i then len:=i;
  for i:=1 to len do pCharReplaceTable[ord(FromChars[i])]:=ord(ToChars[i]);
  end;

procedure ShaCharReplaceProc(var s: AnsiString; pCharReplaceTable: pByteArray);
var
  len: integer;
  p: pInteger;
begin
  len:=Length(s);
  p:=pointer(s);
  while len>0 do begin;
    p^:=pCharReplaceTable[p^ shr 24        ] shl 24
     or pCharReplaceTable[p^ shr 16 and 255] shl 16
     or pCharReplaceTable[p^ shr  8 and 255] shl  8
     or pCharReplaceTable[p^        and 255];
    inc(p);
    dec(len,4);
    end;
  end;

function ShaCharReplaceFunc(const s: AnsiString; pCharReplaceTable: pByteArray): string;
var
  len: integer;
  p, q: pInteger;
begin
  len:=Length(s);
  SetLength(Result, len);
  p:=pointer(s);
  q:=pointer(Result);
  while len>0 do begin;
    q^:=pCharReplaceTable[p^ shr 24        ] shl 24
     or pCharReplaceTable[p^ shr 16 and 255] shl 16
     or pCharReplaceTable[p^ shr  8 and 255] shl  8
     or pCharReplaceTable[p^        and 255];
    inc(p);
    inc(q);
    dec(len,4);
    end;
  end;
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677024
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

не подумайте чего-нибудь плохого, UniqueStr пропал в результате проверок в первой процедуре )
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677025
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub,

Вот результаты полученные с помощью QueryPerformanceCounter:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
const
  z : AnsiString = '1234567890,qwertyuiop,asdfghjkl,zxcvbnm,()-,';
var
  b : int64;
  e : int64;
begin
  QueryPerformanceCounter( b );
  for i := 1 to 10000000 do
    s := ForkReplaceC( z );
  QueryPerformanceCounter( e );
  Memo1.Lines.Add( 'ForkReplaceC: ' + IntToStr( ( e - b ) div 3600 ) );  // 3600 - частота CPU



Видно, что при трех измерениях результаты практически одинаковы:
Код: powershell
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
FastCommatopoint: 1053
UseRepneScasb: 1197
UseLodsD: 685
UseLodsD2: 630
UseLodsB: 731
Rep4Bytes: 846
ForkReplaceC: 655

FastCommatopoint: 1053
UseRepneScasb: 1198
UseLodsD: 685
UseLodsD2: 630
UseLodsB: 730
Rep4Bytes: 844
ForkReplaceC: 654

FastCommatopoint: 1054
UseRepneScasb: 1197
UseLodsD: 683
UseLodsD2: 631
UseLodsB: 729
Rep4Bytes: 845
ForkReplaceC: 656



По моим измерениям видно, что самый быстрый вариант UseLodsD2 :-)
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677027
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub,

если загрузка 100% ядер то увеличивать нет смысла, безусловно. однако обычно ядра недогружены либо из-за дисковых операций либо из-за сети
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677028
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

А строки почему только кратные 4?
SetLength для необнулённого Result в реальном коде, скорее всего, будет давать просадку.
...
Рейтинг: 0 / 0
Быстрая замена символа
    #39677033
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И опять-таки Wide string в пролете, а ведь им уже почти десять лет.
...
Рейтинг: 0 / 0
25 сообщений из 259, страница 5 из 11
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Быстрая замена символа
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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