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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.039 c
2-1169807186
Officeman
2007-01-26 13:26
2007.02.18
Вывод данных с TListView на Принтер


15-1169629958
umbra
2007-01-24 12:12
2007.02.18
как в ХР менять раскладки клавиатуры для досовской программы?


15-1169518575
Spider_NET
2007-01-23 05:16
2007.02.18
Конкурс


11-1148486838
Alexei6021
2006-05-24 20:07
2007.02.18
Перекодировка ANSI-Dos(OEM)


15-1170042568
Slider007
2007-01-29 06:49
2007.02.18
С днем рождения ! 27 января





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