Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.02.18;
Скачать: CL | DM;

Вниз

Оптимизация   Найти похожие ветки 

 
optimizer   (2007-01-22 12:39) [0]

Продолжение ветки.
http://delphimaster.net/view/15-1169395280/


TPassGen = class
 ...
 FBaseLen: DWord;
 FCurPass: String; // есть вариант с array of Char, но скорость не меняется
 FPassBase: String;
end;

{ генерация пароля. входные параметры - Unique - некое число, которое снаружи увеличивается всегда на 1, за счет чего и генерирую пасс, PassLen - длина пароля, контролируется снаружи }
procedure TPassGen.CreatePassword(Unique: DWord; PassLen: DWord);
var
 vMod, i: DWord;
begin
 for i := 1 to PassLen do
 begin
   // FBaseLen - длина словаря
   vMod := Unique mod FBaseLen + 1;
   // FCurPass - результат, FPassBase - словарь
   FCurPass[i] := FPassBase[vMod];
   Unique := Unique div FBaseLen;
 end;
end;


анализировал профилером. больше всего времени отнимает именно эта многократно повторяемая процедура.

возможно ли оптимизировать? судя по всему наибольшее время уходит на операции mod / div. за счет перехода на DWord удалось избежать использования виндового апи (_llmod / _lldiv). из апи используется только UniqueString, от которого можно избавиться при переходе на array of char. но на скорости это не сказывается практически.

при раскладе алфавит = 26 UpperCase Latin, генерация 1-2-3-4 знаковых паролей, скорость составляет порядка 2.1 млн паролей / секунду.

ест еще несколько идей в плане алго для генерации, но, этот, имхо, самый гибкий и удобный (мне). если у кого есть "стоящие" идеи в плане оптимизации - с удовольствием выслушаю.

--
p.s. @модератор: в предыдущей ветке вышла проблема с никами, потому что компьютер рабочий и не я один пользуюсь своим любимым форумом. браузер FireFox, включено автозаполнение.


 
optimizer   (2007-01-22 12:48) [1]

дизасм (для удобства), жирным выделены "некрасивые" места. к сожалению BASMом владею на уровне read-only.


procedure TvPasswordGenerator.CreatePassword (Self: TvPasswordGenerator;
 Unique: Windows.DWORD; PassLen: Windows.DWORD);
var
 vMod: Windows.DWORD;
 i: Windows.DWORD;
begin
00000000 :                               // -- Line #207 --
  00000000 : 53                            PUSH EBX
  00000001 : 56                            PUSH ESI
  00000002 : 57                            PUSH EDI
  00000003 : 55                            PUSH EBP{i}
  00000004 : 51                            PUSH ECX
  00000005 : 8B F2                         MOV ESI,EDX
  00000007 : 8B D8                         MOV EBX,EAX

00000000 :                               // -- Line #208 --
  00000009 : 8B F9                         MOV EDI,ECX{PassLen}
  0000000B : 85 FF                         TEST EDI,EDI
  0000000D : 76 3A                         JBE +58; (0x49)
  0000000F : C7 04 24 01 00 00 00          MOV DWORD PTR [ESP],$00000001
00000000 :                               // -- Line #210 --
  00000016 : 8B C6                         MOV EAX,ESI{Unique}
  00000018 : 33 D2                         XOR EDX,EDX
  0000001A : F7 73 3C                      DIV DWORD PTR [EBX+60{@Self^+60}]
  0000001D : 8B EA                         MOV EBP{i},EDX
  0000001F : 45                            INC EBP{i}
00000000 :                               // -- Line #211 --
  00000020 : 8D 43 50                      LEA EAX,DWORD PTR [EBX+80{@Self^+80}]
  00000023 : E8(00 00 00 00                CALL @UniqueStringA{0x47}
  00000028 : 8B 14 24                      MOV EDX,DWORD PTR [ESP]
  0000002B : 8D 44 10 FF                   LEA EAX,DWORD PTR [EAX+EDX-1]

  0000002F : 50                            PUSH EAX
  00000030 : 8B 43 38                      MOV EAX,DWORD PTR [EBX+56{@Self^+56}]
  00000033 : 8A 44 28 FF                   MOV AL,BYTE PTR [EAX+EBP{vMod}-1]
  00000037 : 5A                            POP EDX
  00000038 : 88 02                         MOV BYTE PTR [EDX],AL
00000000 :                               // -- Line #212 --
  0000003A : 8B C6                         MOV EAX,ESI{Unique}
  0000003C : 33 D2                         XOR EDX,EDX
  0000003E : F7 73 3C                      DIV DWORD PTR [EBX+60{@Self^+60}]
  00000041 : 8B F0                         MOV ESI{Unique},EAX
00000000 :                               // -- Line #213 --
  00000043 : FF 04 24                      INC DWORD PTR [ESP]
00000000 :                               // -- Line #208 --
  00000046 : 4F                            DEC EDI
  00000047 : 75 CD                         JNE -51; (0x16)
00000000 :                               // -- Line #214 --
  00000049 : 5A                            POP EDX
  0000004A : 5D                            POP EBP{i}
  0000004B : 5F                            POP EDI
  0000004C : 5E                            POP ESI
  0000004D : 5B                            POP EBX

  0000004E : C3                            RET NEAR
end;


если бы "облегчить" работу со стеком, попытаться уменьшить влияние mod / div"a. (отказаться от апи UniqueString не проблема, просто не влияет на скорость в масштабах процедуры).

от ООП отказываться глупо. ей богу. слишком крупно все навалено, без классов, и тех приятностей что дает ООП просто не разобраться дальше. просто выдавить бы из этой штуки еще пару миллионов +) ведь реально, имхо.

p.s. вот бы Великий Sha пришел на помощь =)


 
icWasya ©   (2007-01-22 14:51) [2]

попробуй сначала переписать код вот так


procedure TPassGen.CreatePassword(Unique: DWord; PassLen: DWord);
var
vMod, i: DWord;
PCurrPass:PChar;
begin
PCurrPass:=PChar(FCurPass);
for i := 1 to PassLen do
begin
  // FBaseLen - длина словаря
  vMod := Unique mod FBaseLen + 1;
  // FCurPass - результат, FPassBase - словарь
  PCurPass^ := FPassBase[vMod];
  Unique := Unique div FBaseLen;
 Inc(PCurrPass);
end;
end;

должно исчезнуть UniqueString


 
optimizer   (2007-01-22 15:22) [3]

[b]icWasya[/b]
UniqueString конечно исчезнет, но
1. Используем апи LStrToPChar
2. На скорость не влияет (проверил)

Решить можно было и через замену FCurrPass на PChar / array of Char.


 
optimizer   (2007-01-22 15:26) [4]

icWasya
вот дизасм вашего варианта:


procedure TvPasswordGenerator.CreatePassword (Self: TvPasswordGenerator;
 Unique: Windows.DWORD; PassLen: Windows.DWORD);
var
 vMod: Windows.DWORD;
 i: Windows.DWORD;
 PCurPass: System.PChar;
begin
00000000 :                               // -- Line #208 --
  00000000 : 53                            PUSH EBX
  00000001 : 56                            PUSH ESI
  00000002 : 57                            PUSH EDI
  00000003 : 55                            PUSH EBP
  00000004 : 8B E9                         MOV EBP,ECX
  00000006 : 8B F2                         MOV ESI,EDX
  00000008 : 8B D8                         MOV EBX,EAX
00000000 :                               // -- Line #209 --
  0000000A : 8B 43 50                      MOV EAX,DWORD PTR [EBX+80{@Self^+80}]
  0000000D : E8(00 00 00 00                CALL @LStrToPChar{0x49}
  00000012 : 8B F8                         MOV EDI,EAX

00000000 :                               // -- Line #210 --
  00000014 : 8B CD                         MOV ECX,EBP{PassLen}
  00000016 : 85 C9                         TEST ECX,ECX
  00000018 : 76 20                         JBE +32; (0x3A)
00000000 :                               // -- Line #212 --
  0000001A : 8B C6                         MOV EAX,ESI{Unique}
  0000001C : 33 D2                         XOR EDX,EDX
  0000001E : F7 73 3C                      DIV DWORD PTR [EBX+60{@Self^+60}]
  00000021 : 8B C2                         MOV EAX,EDX
  00000023 : 40                            INC EAX
00000000 :                               // -- Line #213 --
  00000024 : 8B 53 38                      MOV EDX,DWORD PTR [EBX+56{@Self^+56}]
  00000027 : 8A 44 02 FF                   MOV AL{vMod},BYTE PTR [EDX+EAX{vMod}-1]
  0000002B : 88 07                         MOV BYTE PTR [EDI{PCurPass}],AL{vMod}
00000000 :                               // -- Line #215 --
  0000002D : 8B C6                         MOV EAX,ESI{Unique}
  0000002F : 33 D2                         XOR EDX,EDX
  00000031 : F7 73 3C                      DIV DWORD PTR [EBX+60{@Self^+60}]
  00000034 : 8B F0                         MOV ESI{Unique},EAX
00000000 :                               // -- Line #216 --
  00000036 : 47                            INC EDI{PCurPass}
00000000 :                               // -- Line #210 --
  00000037 : 49                            DEC ECX
  00000038 : 75 E0                         JNE -32; (0x1A)
00000000 :                               // -- Line #218 --
  0000003A : 5D                            POP EBP
  0000003B : 5F                            POP EDI
  0000003C : 5E                            POP ESI
  0000003D : 5B                            POP EBX
  0000003E : C3                            RET NEAR
end;


 
optimizer   (2007-01-24 17:32) [5]

появилась идея ускорить mod / div путем прегенерации таблиц с рассчитанными значениями... идея ахтунговая, но у напарника скорость выросла в 2 раза.


 
Alx2 ©   (2007-01-25 09:18) [6]

>optimizer   (24.01.07 17:32)
Если Unique снаружи всегда на единицу увеличивается - от деления можно избавиться вообще. Например, ведя инкремент в заданной системе счисления. Увеличивая последний разряд и наблюдая его выход за предельное значение - меняем его на минимальное значение и делаем попытку увеличить следующий разряд. Если же увеличить удалось без переполнения - все ok.

Все-таки в подобных вещах прежде всего думают не о разгоне медленных участков, а о способе их полного исключения.


 
Сергей М. ©   (2007-01-25 10:10) [7]


> если бы "облегчить" работу со стеком


Операции со стеком (сохранение/восстановление РОН) в прологе/эпилоге на практике очень незначительно влияют на сквозную производительность алгоритма п/программы. Но если "ловля блох" все же нужна, то придется отказаться от процедуры с параметрами (по кр.мере для метода ограничиться не более чем двумя cardinal-based-параметрами) и полностью переписать тело процедуры на basm.


 
optimizer   (2007-01-26 05:29) [8]

@Alx2
Простите, не до конца понял идею. Если можно в двух словах, но на пальцах.

@Сергей М.
По поводу стека вы правы, но, имхо, при многотысячном запуске повлияет. "Для метода не более чем двумя" - важный момент - считается ли передача Self"a (которая не видна не вооруженным глазом) как параметр для вашего условия?

С BASMом тяжко, поэтому и обратился к публике. Может кто чего подскажет.

Возможно давно пора отказаться от подобное реализации, но очень удобным является в этом алго то, что любой сгенерированный пасс соответствует некоему уникальному идентификатору и наоборот. Отсюда есть ряд преимуществ в плане гибкости и масштабируемости, хотелось бы добить.

ООП очень сильно сказывается на производительности. Но как избежать падения без потери удобства?


 
Alx2 ©   (2007-01-26 08:57) [9]

>optimizer   (26.01.07 05:29) [8]
Имел в в иду примерно это

procedure TPassGen.IteratePassword(UniqueStart, UniqueStop,
 PassLen: DWord);
var
 i: DWord;
 CounterStr: array of byte;
 tmp: DWord;
 Over: boolean;
 CPRef : Pchar;
begin
 SetLength(CounterStr, PassLen + 1);
 fillchar(CounterStr[0], PassLen + 1, 0);
 SetLength(FCurPass,PassLen);
 CPRef := @FCurPass[1];
 tmp := UniqueStart;
 i := 0;

 while tmp > 0 do
 begin
   CounterStr[i] := tmp mod FBaseLen;
   tmp := tmp div FBaseLen;
   CPRef[i] := FPassBase[CounterStr[i] + 1];
   inc(i);
 end;

 while i<PassLen do
 begin
  CPRef[i] := FPassBase[1];
  inc(i);
 end;

 // Здесь первая генерация FCurrPass готова (для UniqueStart)

 UniqueStart := UniqueStop - UniqueStart;
 while UniqueStart > 0 do
 begin
   dec(UniqueStart);
   i := 0;
   inc(CounterStr[0]);
   over := CounterStr[0] = FBaseLen;
   while over and (i < PassLen) do
   begin
     CounterStr[i] := 0;
     CPRef[i] := FPassBase[1];
     inc(i);
     inc(CounterStr[i]);
     over := CounterStr[i] = FBaseLen;
   end;
   if i < PassLen then
     CPRef[i] := FPassBase[CounterStr[i] + 1];

  // Теперь здесь готова очередная генерация FCurrPass

 end;
end;


И вызов
Var PG: TPassGen;
begin
 PG := TPassGen.Create;
 PG.FPassBase := "012"; // сорри за непосредственный доступ к полям - оно здесь от мово скудоумия
 PG.FBaseLen := 3;
 PG.IteratePassword(5 {С какого значения},100 {по какое},20 {длина цепочки});
end;


 
icWasya ©   (2007-01-26 11:48) [10]

>optimizer   (22.01.07 15:26) [4]
>icWasya
>вот дизасм вашего варианта:

Ну а Вы смотрите, этот код выполняется в цикле или нет?



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

Текущий архив: 2007.02.18;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.042 c
15-1169783659
Slider007
2007-01-26 06:54
2007.02.18
С днем рождения ! 26 января


1-1167212309
Grant
2006-12-27 12:38
2007.02.18
Запись и чтение экземпляра класса в файл


15-1169667249
FIL-23
2007-01-24 22:34
2007.02.18
Коды Хемминга


2-1170242055
asq
2007-01-31 14:14
2007.02.18
графическое отображения связей


9-1143825829
Yegorchic
2006-03-31 21:23
2007.02.18
Поворот FreeForm