delphi tclientdataset

delphi - MidasLib.dcu hace que la aplicación sea más lenta



tclientdataset (3)

Estoy declarando MidasLib para evitar el infierno causado por Midas.dll en algunos clientes.

El siguiente código se ejecuta en aproximadamente 2350 ms. ¡Si elimino la declaración de MidaLib en usos, comienza a ejecutarse en solo 45 ms!

El archivo data.xml se guardó con el método TClientDataSet.SaveToFile, tiene 5000 registros y su tamaño es de aproximadamente 600 Kb.

¿Alguien sabe cómo explicar este extraño comportamiento?

Puedo confirmar el problema en Delphi XE2 upd 3 y en Delphi XE3 upd 2.

Gracias.

program Loader; {$APPTYPE CONSOLE} {$R *.res} uses MidasLib, System.SysUtils, Winapi.Windows, Data.DB, Datasnap.DBClient; var cds : TClientDataSet; start, stop : Cardinal; begin cds := TClientDataSet.Create(nil); try start := GetTickCount; cds.LoadFromFile(''c:/temp/data.xml''); stop := GetTickCount; Writeln(Format(''Time elapsed: %dms'', [stop-start])); finally cds.Free; end; end.



No estoy seguro de por qué piensas que necesitas usar MidasLib para "evitar el infierno de DLL".

Cuando el RTL llama a TCustomClientDataSet.CreateDSBase , esto llama a CheckDbClient en DSIntf.Pas. Es esta rutina la que determina qué instancia de Midas.Dll se carga al examinar el registro.

Por lo tanto, podría asegurarse de que se utilice una instancia particular de Midas.Dll asegurándose de que el registro refleje su ubicación antes de CheckDbClient . La configuración de registro es InProcServer32 en HK_Classes_Root/CLSId/{9E8D2FA1-591C-11D0-BF52-0020AF32BD64} . Se puede actualizar llamando a RegisterComServer especificando la ruta y el nombre de archivo de Midas, sujeto a los permisos necesarios de acceso al registro, por supuesto.


Solo usamos una copia local de la DLL de Midas independientemente de lo que esté instalado en el sistema, y ​​solo volvemos a la global, si no se encuentra una local.

Usamos XE2 upd4 hf1 y luego cambiamos a Midas DLL de XE4 (el proyecto principal aún está hecho con xe2)

// based on stock MidasLib unit unit MidasDLL; interface implementation uses Winapi.Windows, Winapi.ActiveX, Datasnap.DSIntf, SysUtils, Registry; // function DllGetDataSnapClassObject(const CLSID, IID: TGUID; var Obj): HResult; stdcall; external ''Midas.DLL''; //var DllGetDataSnapClassObject: function(const CLSID, IID: TGUID; var Obj): HResult; stdcall; //external ''Midas.DLL''; var DllGetDataSnapClassObject: pointer; //external ''Midas.DLL''; const dllFN = ''Midas.DLL''; dllSubN = ''DllGetDataSnapClassObject''; var DllHandle: HMODULE = 0; function RegisteredMidasPath: TFileName; const rpath = ''/SOFTWARE/Classes/CLSID/{9E8D2FA1-591C-11D0-BF52-0020AF32BD64}/InProcServer32''; var rry: TRegistry; begin Result := ''''; rry := TRegistry.Create( KEY_READ ); try rry.RootKey := HKEY_LOCAL_MACHINE; if rry.OpenKeyReadOnly( rpath ) then begin Result := rry.ReadString(''''); if not FileExists( Result ) then Result := ''''; end; finally rry.Destroy; end; end; procedure TryFindMidas; var fPath, msg: string; function TryOne(const fName: TFileName): boolean; const ver_16_0 = 1048576; // $00060001 var ver: Cardinal; ver2w: LongRec absolute ver; begin Result := false; ver := GetFileVersion( fName ); if LongInt(ver)+1 = 0 then exit; // -1 --> not found if ver < ver_16_0 then begin msg := msg + #13#10 + ''Obsolete version found: ''+IntToStr(ver2w.Hi) + ''.'' + IntToStr(ver2w.Lo) + '' in library file '' + fName; exit; end; DllHandle := SafeLoadLibrary(fName); if DllHandle = 0 then begin msg := msg + #13#10 + ''Failure loading library '' + fName + ''. Maybe this was Win64 DLL or some other reason.''; exit; end; DllGetDataSnapClassObject := GetProcAddress( DllHandle, dllSubN); if nil = DllGetDataSnapClassObject then begin // не найдена msg := msg + #13#10 + ''Incompatible library loaded '' + fName + ''. Missed function '' + dllSubN; FreeLibrary( DllHandle ); DllHandle := 0; end; Result := true; end; function TryTwo(const fName: TFileName): boolean; // seek in the given folder and its immediate parent begin Result := TryOne(fName + dllFN); if not Result then Result := TryOne(fName + ''../' + dllFN); // end; begin fPath := ExtractFilePath( ParamStr(0) ); if TryTwo( fPath ) then exit; fPath := IncludeTrailingBackslash( GetCurrentDir() ); if TryTwo( fPath ) then exit; fPath := RegisteredMidasPath; if fPath > '''' then if TryOne( fPath ) then exit; msg := ''This program needs the library '' + dllFN + '' version 16.0 or above.''#13#10 + ''It was not found, thus the program can not work.''#13#10 + #13#10 + msg; Winapi.Windows.MessageBox(0, PChar(msg), ''Launch failure!'', MB_ICONSTOP or MB_TASKMODAL or MB_DEFAULT_DESKTOP_ONLY or MB_TOPMOST ); Halt(1); end; initialization // RegisterMidasLib(@DllGetDataSnapClassObject); -- static linking does not work for utilities in sub-folders TryFindMidas; // immediately terminates the application if not found RegisterMidasLib(DllGetDataSnapClassObject); finalization if DllHandle <> 0 then if FreeLibrary( DllHandle ) then DllHandle := 0; end.