Показать полную графическую версию : Скрипты Inno Setup. Помощь и советы [часть 9]
alexander-mex
18-04-2019, 15:09
Спасибо! Попробую
Можно ли сделать с помощью этой программы сборник, чтобы открывалось окно и я мог выбрать, что хочу установить?
Сделано на Inno Setup (https://c.radikal.ru/c31/1904/1a/96f682ef75e3.png)
Сделано на Inno Setup (https://b.radikal.ru/b20/1904/b8/b3bf7880105e.png)
ROMKA-1977
27-04-2019, 01:04
Здраствуйте. Подскажите пож. константу папки Сохраненные игры (C:\Users\XXX\Saved Games). В справке такой нет.
habib2302
27-04-2019, 01:39
ROMKA-1977, как вариант {sd}\Users\{username}\Saved Games
или
[Code]
if RegValueExists(HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders', '{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}') then
begin
// The value exists
end;
end;
или
{reg:HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders,%7B{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}}
{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4} = это путь к папке в случае если пользователь изменит путь через свойства. Проверил от 7 и до 10. Везде один и тот же {4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}
habib2302
27-04-2019, 14:07
ROMKA-1977, или же
%USERPROFILE%\Saved Games
ErikPshat
27-04-2019, 19:43
Так здесь проблема с программистами, которые в XXI веке продолжают считать, что в мире не существует никакого иного языка, кроме английского. »
Ага, тут в продолжение разговора, я всё-таки решил использовать эту злополучную утилиту, которая не понимает в путях не только символы кириллицы, но и другие нестандартные символы, отличные от букв и цифр ANSI алфавита: [A-z0-9]. Вообщем мне удалось соорудить проверку на символы кириллицы и оно прекрасно работает.
Наверху кода создаю такую функцию:
function IsAnsi(S: String): Boolean; var S1, S2: string;
begin S1 := AnsiUppercase(S); S2 := Uppercase(S); if CompareStr(S1, S2) = 0 then
begin S1 := Lowercase(S); S2 := AnsiLowercase(S); if CompareStr(S1, S2) = 0 then
Result := True;
end;
end;
А потом, там где я хочу произвести проверку, вставляю код проверки символов в пути к папке программы и при обнаружении вывожу предупреждение с завершением работы:
if not (IsAnsi(ExpandConstant('{src}'))) then
begin MsgBox(ExpandConstant('{cm:CirillicPATH}')+#10#10+ExpandConstant('{src}'),mbError,MB_OK);
Exit;
end;Но теперь я хочу дополнить проверку и на нестандартные символы, типа !, "@, #, $, %, ^, &, *,...
В инете нашёл (https://stackoverflow.com/questions/24940209/required-a-number-in-text-box-in-inno-setup) такую интересную процедуру определения символов по их номерам и даже по диапазонам номеров в десятичном виде:
procedure justNumbers(Sender: TObject; var Key: Char);
begin
if not ((Key = #8) or (Key = #43) or ((Key >= #48) and (Key <= #57))) then
begin
Key := #0;
end;
end;
Но вот что-то никак ума не приложу, как бы мне теперь объединить эти две конструкции, чтобы и символы кириллицы анализировала, и нестандартные символы определяла?
Либо отказаться от первой функции и сделать определение символов по их номерам?
Чую собака неглубоко зарыта, но что-то у меня пока не получается никак.
usermode
28-04-2019, 22:54
Для одного из проектов искал самый быстрый подсчет crc32 для файлов и решил сделать dll, кому интересно забирайте в аттаче.
Алгоритм работает так: если поддержку SSE 4.2 процессор имеет, срабатывает аппаратный подсчет crc32c (с - использование Intel полинома: $1EDC6F41), в противном случае, если процессор слишком старый и не имеет поддержку SSE 4.2, то срабатывает crc32cfast с оптимизацией на ассемблере (имеет тот же результат подсчета). отличие результата подсчета от стандартного crc32 только из-за использования другого инициализационного полинома.
По заверению авторов кода, результаты подсчета следующие:
- Our optimized unrolled x86 version - aka crc32cfast() - performs the test at a very good pace of 1.7 GB/s;
- SSE 4.2 version - aka crc32csse42() - gives an amazing 3.7 GB/s speed (on both Win32 and Win64 platforms);
- simple rolled version of the algorithm (similar to the one in Delphi zlib unit) runs at 330 MB/s.
Основано на:
https://synopse.info/fossil/info/8fe7cc53b7
ErikPshat
29-04-2019, 09:01
usermode, ещё одна DLL конечно никогда не помешает. Только в наши времена подсчёт CRC32 имеет актуальность на маленьких файлах, пускай даже самый быстрый подсчёт CRC32. По крайней мере даже MD5 быстрее подсчитывается стандартной функцией препроцессора GetMD5OfFile, не говоря уже про более точный SHA-1 и более быстрый подсчёт больших файлов по 1-4-10-20 Гига стандартной функцией препроцессора GetSHA1OfFile. Может быть я ошибаюсь, вашу утилиту не пробовал, но на практике часто приходится подсчитывать файлы по 4 и более Гб, так вот, какой бы быстрый не был бы CRC32, так это можно уснуть надолго, тогда как SHA-1 обычно замечено мною, что на несколько махов быстрее подсчитывается :)
Кстати, стоит мне изменить путь s:='D:\somebigfile.dat'; или подсунуть по этому пути реальный файл, как прога тут же выдаёт ошибку:
https://i2.imageban.ru/out/2019/04/29/2ef15e077ca73dde340a0aba71c3fcbf.png (https://i1.imageban.ru/out/2019/04/29/37e0528ee1f8e7fad05d2766d1ba0258.png) https://i2.imageban.ru/out/2019/04/29/3309b1e05d33af649ca213dd55912f1b.png (https://i2.imageban.ru/out/2019/04/29/d96209da4f7783030730c277ce0e916f.png)
Ну а мне никто так и не поможет?
usermode
29-04-2019, 11:32
ErikPshat, у меня dll на всех ОС, включая Windows 10, работает нормально. Может причина в "неуниверсальных" параметрах выделения или освобождения памяти.
Можно попросить протестировать "болванку" на дельфи? Нужно прописать путь к существующему файлу, нажать каждую кнопку и сообщить, на каких будут ошибки. Заодно сравните на гигабайтных файлах скорость подсчета сравнительно md5 и sha-1 (предпочтительно на ssd при наличии) и убедитесь в обратном :)
У меня на ssd подсчитывает фильм 2.22 Gb стандартной системной реализацией за 4.8sec, sse4.2 за 0.8sec, fast assembler за 1.2 sec.
Ну а мне никто так и не поможет?
когда-то давно писал такой "дурацкий" код на проверку символов, которые указаны в abc, все остальные несуществующие символы будут отсчитывать ошибку.
procedure InitializeWizard;
var
i,j: integer;
s,abc: string;
begin
j := 0;
abc := '0123456789абв%*@abc';
s:='012';
for i:=1 to Length(s) do
begin
if Pos(s[i],abc) = 0 then
inc(j);
end;
if j >= 1 then
begin
MsgBox('Error! 0123456789абв%*@abc chars only are allowed!', mbInformation, MB_OK);
Exit;
end;
end;
лучше учесть те символы, что можно, чем учитывать все, что нельзя.
add
причина ошибки dll в некорректном определении технологии SSE 4.2, там где ее нет, например на CPU с SSE 4.1, она определяется что есть.
ErikPshat
29-04-2019, 14:26
причина ошибки dll в некорректном определении технологии SSE 4.2, там где ее нет, например на CPU с SSE 4.1, она определяется что есть. »
Ну вот, значит нужно над совместимостью поработать ;)
https://i2.imageban.ru/out/2019/04/29/295fb142e66faf6f7bab15206b780672.png (https://i4.imageban.ru/out/2019/04/29/b1ce6ad43a1f640dfa5e3085ee3294f6.gif)
За код спасибо, правда я видел подобные варианты, но видимо это самый универсальный вариант, правда я хотел бы взять диапазон через Key: Char по нумерации в таблице ASCII-символов.
usermode
29-04-2019, 15:01
CRC32-C Ansi/Unicode Dlls *fixed*
Пришлось исправлять косяки разработчиков, плохо работало определение наличия технологии SSE 4.2 (кто ж мог подумать :) )
в оригинале:
test edx,$100000 // перепутали регистр, по которому берется информация для SSE 4.2
setz al // неправильная установка флага
исправленный:
test ecx,$100000 // fix
setne al // fix
фикс основан на интеловских доках, где достаточно сделать проверку только на поддержку SSE 4.2:
https://software.intel.com/en-us/articles/using-cpuid-to-detect-the-presence-of-sse-41-and-sse-42-instruction-sets
ErikPshat
29-04-2019, 17:24
usermode, окей, теперь работает. Но так не честно. Чтобы быть объективным, тогда уж надо подсчитать время и потом сравнивать посекундно, какая функция ведёт подсчёт быстрее. Вот так я подсчитал время перед стартом подсчёта контрольной суммы и после, заодно можно сравить по времени подсчёт MD5 и SHA-1 того же файла:
;InnoSetupVersion=5.6.1 (Unicode)
#define CP = (Defined UNICODE) ? "unicode" : "ansi"
[Setup]
AppName=test
AppVerName=test
OutputDir=...
OutputBaseFilename=HachCheck
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;
[*Code*]
function GetCRC32COfFile(FilePath: String): Cardinal;
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
procedure InitializeWizard;
var
md5, sha1, t1, t2, t3, t4, t5, t6, f1, FileName: string;
crc: cardinal;
begin
if GetOpenFileName(ExpandConstant('Выберите файл'),FileName,ExpandConstant('{src}'),ExpandConstant('Выбрать любой файл ')+'(*.*)|*.*','*') then
if MsgBox(ExpandConstant('Выбран файл')+#10#10+FileName+#10#10+ExpandConstant('Подсчитать контрольную сумму файла "'+ExtractFileName(FileName)+'" ?'), mbInformation, MB_YESNO) = IDYES then
begin
if FileExists(FileName) then
begin
t1:=GetDateTimeString('hh:nn:ss', '-', ':');
crc:=GetCRC32COfFile(FileName);
t2:=GetDateTimeString('hh:nn:ss', '-', ':');
f1:=Format('%.8x',[crc]);
MsgBox(ExpandConstant('Старт вычисления: '+t1)+#10+#10+ExpandConstant('Хэш сумма CRC32: '+f1)+#10#10+ExpandConstant('Конец вычисления: '+t2), mbInformation, MB_OK);
end;
begin
t3:=GetDateTimeString('hh:nn:ss', '-', ':');
md5:=GetMD5OfFile(FileName);
t4:=GetDateTimeString('hh:nn:ss', '-', ':');
MsgBox(ExpandConstant('Старт вычисления: '+t3)+#10+#10+ExpandConstant('Хэш сумма MD5: '+md5)+#10#10+ExpandConstant('Конец вычисления: '+t4), mbInformation, MB_OK);
end;
begin
t5:=GetDateTimeString('hh:nn:ss', '-', ':');
sha1:=GetSHA1OfFile(FileName);
t6:=GetDateTimeString('hh:nn:ss', '-', ':');
MsgBox(ExpandConstant('Старт вычисления: '+t5)+#10+#10+ExpandConstant('Хэш сумма SHA-1: '+sha1)+#10#10+ExpandConstant('Конец вычисления: '+t6), mbInformation, MB_OK);
end;
MsgBox(ExpandConstant('CRC32 :'+#10#10+'Старт вычисления: '+t1)+#10+#10+ExpandConstant('Конец вычисления: '+t2)+#10+#10+#10+
ExpandConstant('MD5 :'+#10#10+'Старт вычисления: '+t3)+#10+#10+ExpandConstant('Конец вычисления: '+t4)+#10+#10+#10+
ExpandConstant('SHA-1 :'+#10#10+'Старт вычисления: '+t5)+#10+#10+ExpandConstant('Конец вычисления: '+t6), mbInformation, MB_OK);
end;
end;
Лучше видно будет на больших файлах, где-то 2-4 Гб, чем больше - тем очевиднее. Вот тогда можно и рассудить.
Вот пример вычисления чек-сумм файла 3,80 ГБ:
https://i4.imageban.ru/out/2019/04/29/57ac3b3dcbf274e20a5d860575b52084.png (https://i6.imageban.ru/out/2019/04/29/9da6c89f353cd0f5857dcd38b7a7594a.png)
CRC32: 01 мин 32 сек
M D 5 : 00 мин 39 сек
SHA-1 : 01 мин 52 сек
MD5 у меня всегда почему-то быстрее всего подсчитывает.
Dodakaedr
29-04-2019, 19:58
Но вот что-то никак ума не приложу, как бы мне теперь объединить эти две конструкции, чтобы и символы кириллицы анализировала, и нестандартные символы определяла? »
Такой вариант сойдет?
function IsAnsiOrSym(S: String): Boolean;
var
n: string;
i,j: integer;
begin
if CompareStr(AnsiUppercase(S), Uppercase(S)) = 0 then
if CompareStr(Lowercase(S), AnsiLowercase(S)) = 0 then Result := True;
if result then
begin
n := '!"@#$%^&*';
for i:=1 to length(s) do
for j:=1 to length(n) do
begin
if s[i] = n[j] then
begin
Result := False;
exit;
end;
end;
end;
end;
usermode
30-04-2019, 01:16
ErikPshat, а у меня такие результаты на ssd на файле в 2.22Gb:
#define CP = (Defined UNICODE) ? "unicode" : "ansi"
[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;
[.Code]
function GetCRC32COfFile(FilePath: String): Cardinal;
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
function GetTickCount: Dword;
external 'GetTickCount@kernel32.dll stdcall';
function FormatTime(time: int64): string;
var
Ms : Int64;
H, M, S : Integer;
begin
Ms := time;
H := Ms div (60 * 60 * 1000);
Ms := Ms mod (60 * 60 * 1000);
M := Ms div (60 * 1000);
Ms := Ms mod (60 * 1000);
S := Ms div 1000;
Ms := Ms mod 1000;
Result := Format('%.2dh:%.2dm:%.2ds:%.3dms',[H,M,S,Ms]);
end;
///////////////////////////
procedure InitializeWizard;
var
s: string;
c: cardinal;
Elapsed,Start,Stop:int64;
begin
s:='C:\44.txt';
if FileExists (s) then
begin
Elapsed := 0;
Start:=GetTickCount;
c:=GetCRC32COfFile(s);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(Format('%.8x',[c])+' Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
/////////////
Elapsed := 0;
Start:=GetTickCount;
s:=GetMD5OfFile(s);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(s+' Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
end;
end;
C5433036 Time: 00h:00m:00s:842ms
---------------------------
9e7592826a085607311cd0a38f17ef19 Time: 00h:00m:04s:602ms
p.s. там еще может быть момент "первого чтения". когда доступ к диску замедлен, либо тот же диск интенсивно задействован прриложениями, тогда изначально может показаться что CRC32 "тормозит", но на самом деле оно всяко быстрее md5, по крайней мере на моем Core i7 процессоре.
ErikPshat
30-04-2019, 02:48
Такой вариант сойдет? »
О, да! Думаю, самый оптимальный и самый хитрый и короткий вариант. Как раз то, что надо. Я ещё отдельно выставил 2 разные переменные в первой и второй проверке и вывожу 2 разных сообщения: по поводу символов кириллицы и по поводу нестандартных символов. То есть, теперь распознавание получается более точнее, нежели одно общее. Спасибо ещё раз!!!
C5433036 Time: 00h:00m:00s:842ms
---------------------------
9e7592826a085607311cd0a38f17ef19 Time: 00h:00m:04s:602ms »
Видимо у вас процессор использует инструкции процессора SSE 4.2 и код DLL просто заточен и оптимизирован под эти инструкции, вот и получается у вас подсчёт CRC32 быстрее, т.к. инструкции MD5 не оптимизированы.
А у меня, как я ранее выкладывал скриншот своего процессора на нетбуке Asus Eee PC 1215N Intel Atom D525, то у него SSE3 максимум, поэтому MD5 вычисляется намного быстрее. Вот результаты на файле 3,77 ГБ:
CRC - 01 мин 53 сек 975 мс - https://i1.imageban.ru/out/2019/04/30/36ab596138f21ff13c3f02cf95ba6b23.png
MD5 - 00 мин 39 сек 328 мс - https://i4.imageban.ru/out/2019/04/30/260cffc566b347d26e6f959ac9652146.png
Так что, ваш код DLL получается только для избранных выигрышный. Может быть его как-то оптимизировать под SSE3?
usermode
30-04-2019, 11:06
Может быть его как-то оптимизировать под SSE3? »
только начиная с SSE 4.2 есть аппаратная инструкция crc32. в dll используется самый оптимизированный подсчет на ассемблере даже без SSE 4.2, не знаю в чем магия, утверждать и спорить не буду, но в очередной раз предположу: скорость чтения с ноутбучного hdd, до 110-120 мегабайт в секунду, ssd до 550 mb/s. По заявлениям разработчиков на современных Intel процессорах скорость подсчета алгоритма crc32cfast - 1.7 Gb/s, crc32csse42 - 3.5 Gb/s. Такого чтения не может обеспечить любой адекватный носитель.
А попробуйте еще виндовый апишный подсчет crc32, будет ли он у вас быстрее, чем подсчет в dll (у меня виндовый подсчет медленнее в 10 раз):
#define CP = (Defined UNICODE) ? "unicode" : "ansi"
#define AW = (Defined UNICODE) ? "W" : "A"
[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;
[.Code]
type
TMyMsg = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
function GetCRC32COfFile(FilePath: String): Cardinal;
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
function GetTickCount: Dword;
external 'GetTickCount@kernel32.dll stdcall';
function RtlComputeCrc32(dwInitial: Cardinal; const pData: Longint; iLen: Integer): Cardinal;
external 'RtlComputeCrc32@ntdll.dll stdcall';
function ReadFile(hFile: THandle; lpBuffer: Longint; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: Longint): BOOL;
external 'ReadFile@kernel32.dll stdcall';
function GetProcessHeap: THandle;
external 'GetProcessHeap@kernel32.dll stdcall';
function HeapAlloc(hHeap: THandle; dwFlags, dwBytes: DWORD): Longint;
external 'HeapAlloc@kernel32.dll stdcall';
function HeapSize(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): DWORD;
external 'HeapSize@kernel32.dll stdcall';
function HeapFree(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): BOOL;
external 'HeapFree@kernel32.dll stdcall';
function PeekMessage(var lpMsg: TMyMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
external 'PeekMessage{#AW}@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMyMsg): BOOL;
external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: TMyMsg): Longint;
external 'DispatchMessage{#AW}@user32.dll stdcall';
function CreateFile(lpFileName: String; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFile{#AW}@kernel32.dll stdcall';
function CloseHandle(hObject: THandle): BOOL;
external 'CloseHandle@kernel32.dll stdcall';
const
PAGE_READONLY = $0002;
FILE_MAP_READ = $0004;
HEAP_ZERO_MEMORY = $0008;
FILE_FLAG_SEQUENTIAL_SCAN = $08000000;
GENERIC_READ = $80000000;
GENERIC_WRITE = $40000000;
GENERIC_EXECUTE = $20000000;
GENERIC_ALL = $10000000;
FILE_SHARE_READ = 1;
FILE_SHARE_WRITE = 2;
FILE_SHARE_DELETE = 4;
CREATE_NEW = 1;
CREATE_ALWAYS = 2;
OPEN_EXISTING = 3;
OPEN_ALWAYS = 4;
TRUNCATE_EXISTING = 5;
INVALID_HANDLE_VALUE = (-1);
procedure AppProcessMessage;
var
Msg: TMyMsg;
begin
while PeekMessage(Msg, 0, 0, 0, 1) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
function GetCRC32OfFile(FileName: string): Cardinal;
var
hFile, hHeap: THandle;
lpBuffer: Longint;
dwBufferSize, dwRead: DWORD;
begin
Result := 0;
hFile := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if hFile = INVALID_HANDLE_VALUE then Exit;
try
hHeap := GetProcessHeap;
if hHeap = 0 then Exit;
lpBuffer := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 32*1024);
if lpBuffer = 0 then Exit;
dwBufferSize := HeapSize(hHeap, 0, lpBuffer);
if dwBufferSize = 0 then Exit;
while ReadFile(hFile, lpBuffer, dwBufferSize, dwRead, 0) and BOOL(dwRead > 0) do
begin
AppProcessMessage;
Result := RtlComputeCrc32(Result, lpBuffer, dwRead);
end;
finally
if hHeap <> 0 then
HeapFree(hHeap, 0, lpBuffer);
CloseHandle(hFile);
end;
end;
function FormatTime(time: cardinal{int64}): string;
var
Ms : cardinal{int64};
H, M, S : Integer;
begin
Ms := time;
H := Ms div (60 * 60 * 1000);
Ms := Ms mod (60 * 60 * 1000);
M := Ms div (60 * 1000);
Ms := Ms mod (60 * 1000);
S := Ms div 1000;
Ms := Ms mod 1000;
Result := Format('%.2dh:%.2dm:%.2ds:%.3dms',[H,M,S,Ms]);
end;
///////////////////////////
procedure InitializeWizard;
var
s: string;
c: cardinal;
Elapsed,Start,Stop:cardinal{int64};
begin
s:='C:\44.txt';
if FileExists (s) then
begin
Elapsed := 0;
Start:=GetTickCount;
c:=GetCRC32OfFile(s);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(Format('%.8x',[c])+' Api CRC32 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
/////////////
Elapsed := 0;
Start:=GetTickCount;
c:=GetCRC32COfFile(s);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(Format('%.8x',[c])+' Fast CRC-32C Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
/////////////
Elapsed := 0;
Start:=GetTickCount;
s:=GetMD5OfFile(s);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(s+' Inno MD5 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
end;
end;
В интернетах должна быть реализация md5 под sse2, хотя некоторые разработчики для своих брутилок тоже делали на ассемблере очень быстрые алгоритмы :)
ErikPshat
30-04-2019, 11:53
А попробуйте еще виндовый апишный подсчет crc32, будет ли он у вас быстрее, чем подсчет в dll (у меня виндовый подсчет медленнее в 10 раз) »
Ну на файле 3,8 Гб
API: 01:53:085
Fast CRC-32C: 00:07:801
MD5: 00:15:787
Пару раз прогонял, результаты почти практически такие же. Fast CRC-32C конечно намного быстрее считает, только почему-то CRC разные показывает :)
if s[i] = n[j] then »
Эмм, что-то у меня это равенство ни при каких условиях не выполняется, хоть есть нестандартные символы, хоть нет.
usermode
30-04-2019, 12:05
Fast CRC-32C конечно намного быстрее считает »
полагаю, что проблема замедленного подсчета , это первичный доступ чтения, чтобы убедиться, переместите в скрипте код подсчета md5 на первое место - будет ли средний результат в тех же 15 секунд.
только почему-то CRC разные показывает »
это потому, что в CRC-32C используется другой Intel-овский полином (приставка С намекает), но сам алгоритм абсолютно идентичный.
ErikPshat
30-04-2019, 12:30
usermode, переместил MD5 на первое место, то же самое: 00:15:678
А вот API CRC32: 00:00:015 - как так возможно? :)
А Fast CRC-32C: 00:00:000 :)
В общем, на первом результате происходит долгое ожидание, такое впечатление, что файл просто сначала кэшируется во временную память, ну и на раскрутку цилиндров видимо тратится время. А второй и третий результат выдаётся практически тут же.
usermode
30-04-2019, 12:49
А вот API CRC32: 00:00:015 - как так возможно?
А Fast CRC-32C: 00:00:000 »
сказывается 3 день Пасхи :) не назначил отдельную переменную для имени файла, и s потом вместо файла указывало на посчитанную ранее md5 сумму.
#define CP = (Defined UNICODE) ? "unicode" : "ansi"
#define AW = (Defined UNICODE) ? "W" : "A"
[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
CreateAppDir=no
Uninstallable=no
CreateUninstallRegKey=no
[Files]
Source: crc32c_{#CP}.dll; Flags: dontcopy;
[.Code]
type
TMyMsg = record hWnd: HWND; msg, wParam: Word; lParam: LongWord; Time: TFileTime; pt: TPoint; end;
function GetCRC32COfFile(FilePath: String): Cardinal;
external 'GetCRC32COfFile@files:crc32c_{#CP}.dll stdcall';
function GetTickCount: Dword;
external 'GetTickCount@kernel32.dll stdcall';
function RtlComputeCrc32(dwInitial: Cardinal; const pData: Longint; iLen: Integer): Cardinal;
external 'RtlComputeCrc32@ntdll.dll stdcall';
function ReadFile(hFile: THandle; lpBuffer: Longint; nNumberOfBytesToRead: DWORD; var lpNumberOfBytesRead: DWORD; lpOverlapped: Longint): BOOL;
external 'ReadFile@kernel32.dll stdcall';
function GetProcessHeap: THandle;
external 'GetProcessHeap@kernel32.dll stdcall';
function HeapAlloc(hHeap: THandle; dwFlags, dwBytes: DWORD): Longint;
external 'HeapAlloc@kernel32.dll stdcall';
function HeapSize(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): DWORD;
external 'HeapSize@kernel32.dll stdcall';
function HeapFree(hHeap: THandle; dwFlags: DWORD; lpMem: Longint): BOOL;
external 'HeapFree@kernel32.dll stdcall';
function PeekMessage(var lpMsg: TMyMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL;
external 'PeekMessage{#AW}@user32.dll stdcall';
function TranslateMessage(const lpMsg: TMyMsg): BOOL;
external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: TMyMsg): Longint;
external 'DispatchMessage{#AW}@user32.dll stdcall';
function CreateFile(lpFileName: String; dwDesiredAccess: DWORD; dwShareMode: DWORD; lpSecurityAttributes: DWORD; dwCreationDisposition: DWORD; dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle;
external 'CreateFile{#AW}@kernel32.dll stdcall';
function CloseHandle(hObject: THandle): BOOL;
external 'CloseHandle@kernel32.dll stdcall';
const
PAGE_READONLY = $0002;
FILE_MAP_READ = $0004;
HEAP_ZERO_MEMORY = $0008;
FILE_FLAG_SEQUENTIAL_SCAN = $08000000;
GENERIC_READ = $80000000;
GENERIC_WRITE = $40000000;
GENERIC_EXECUTE = $20000000;
GENERIC_ALL = $10000000;
FILE_SHARE_READ = 1;
FILE_SHARE_WRITE = 2;
FILE_SHARE_DELETE = 4;
CREATE_NEW = 1;
CREATE_ALWAYS = 2;
OPEN_EXISTING = 3;
OPEN_ALWAYS = 4;
TRUNCATE_EXISTING = 5;
INVALID_HANDLE_VALUE = (-1);
procedure AppProcessMessage;
var
Msg: TMyMsg;
begin
while PeekMessage(Msg, 0, 0, 0, 1) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
function GetCRC32OfFile(FileName: string): Cardinal;
var
hFile, hHeap: THandle;
lpBuffer: Longint;
dwBufferSize, dwRead: DWORD;
begin
Result := 0;
hFile := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if hFile = INVALID_HANDLE_VALUE then Exit;
try
hHeap := GetProcessHeap;
if hHeap = 0 then Exit;
lpBuffer := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 32*1024);
if lpBuffer = 0 then Exit;
dwBufferSize := HeapSize(hHeap, 0, lpBuffer);
if dwBufferSize = 0 then Exit;
while ReadFile(hFile, lpBuffer, dwBufferSize, dwRead, 0) and BOOL(dwRead > 0) do
begin
AppProcessMessage;
Result := RtlComputeCrc32(Result, lpBuffer, dwRead);
end;
finally
if hHeap <> 0 then
HeapFree(hHeap, 0, lpBuffer);
CloseHandle(hFile);
end;
end;
function FormatTime(time: int64): string;
var
Ms : int64;
H, M, S : Integer;
begin
Ms := time;
H := Ms div (60 * 60 * 1000);
Ms := Ms mod (60 * 60 * 1000);
M := Ms div (60 * 1000);
Ms := Ms mod (60 * 1000);
S := Ms div 1000;
Ms := Ms mod 1000;
Result := Format('%.2dh:%.2dm:%.2ds:%.3dms',[H,M,S,Ms]);
end;
///////////////////////////
procedure InitializeWizard;
var
s,fs: string;
c: cardinal;
Elapsed,Start,Stop:int64;
begin
fs:='C:\44.txt';
if FileExists (fs) then
begin
Elapsed := 0;
Start:=GetTickCount;
s:=GetMD5OfFile(fs);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(s+' Inno MD5 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
/////////////
Elapsed := 0;
Start:=GetTickCount;
c:=GetCRC32OfFile(fs);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(Format('%.8x',[c])+' Api CRC32 Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
/////////////
Elapsed := 0;
Start:=GetTickCount;
c:=GetCRC32COfFile(fs);
Stop:=GetTickCount;
Elapsed:=Stop-Start;
MsgBox(Format('%.8x',[c])+' Fast CRC-32C Time: '+FormatTime(Elapsed), mbInformation, MB_OK);
end;
end;
ErikPshat,
http://qaru.site/questions/332124/crc32-vs-crc32c
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.