クラスに静的カウントメンバーを追加せずに、Delphi7のメモリ内の特定のクラスのカウントを追跡するにはどうすればよいですか。プログラムのパフォーマンスを追跡するため。よろしくお願いします。
2 に答える
4
NewInstanceメソッドとFreeInstanceメソッドをクラスVMTにフックできます。
unit ClassHook;
{no$DEFINE SINGLE_THREAD}
interface
var
BitBtnInstanceCounter: integer;
implementation
uses Windows, Buttons;
function GetVirtualMethod(AClass: TClass; const VmtOffset: Integer): Pointer;
begin
Result := PPointer(Integer(AClass) + VmtOffset)^;
end;
procedure SetVirtualMethod(AClass: TClass; const VmtOffset: Integer; const Method: Pointer);
var
WrittenBytes: {$IF CompilerVersion>=23}SIZE_T{$ELSE}DWORD{$IFEND};
PatchAddress: PPointer;
begin
PatchAddress := Pointer(Integer(AClass) + VmtOffset);
WriteProcessMemory(GetCurrentProcess, PatchAddress, @Method, SizeOf(Method), WrittenBytes);
end;
{$IFOPT W+}{$DEFINE WARN}{$ENDIF}{$WARNINGS OFF} // avoid compiler "Symbol 'xxx' is deprecated" warning
const
vmtNewInstance = System.vmtNewInstance;
vmtFreeInstance = System.vmtFreeInstance;
{$IFDEF WARN}{$WARNINGS ON}{$ENDIF}
type
TNewInstanceFn = function(Self: TClass): TObject;
TFreeInstanceProc = procedure(Self: TObject);
var
OrgTBitBtn_NewInstance: TNewInstanceFn;
OrgTBitBtn_FreeInstance: TFreeInstanceProc;
function TBitBtn_NewInstance(Self: TClass): TObject;
begin
Result := OrgTBitBtn_NewInstance(Self);
{$IFDEF SINGLE_THREAD}
Inc(BitBtnInstanceCounter);
{$ELSE}
InterlockedIncrement(BitBtnInstanceCounter);
{$ENDIF}
end;
procedure TBitBtn_FreeInstance(Self: TObject);
begin
{$IFDEF SINGLE_THREAD}
Dec(BitBtnInstanceCounter);
{$ELSE}
InterlockedDecrement(BitBtnInstanceCounter);
{$ENDIF}
OrgTBitBtn_FreeInstance(Self);
end;
procedure InstallHooks;
begin
OrgTBitBtn_NewInstance := GetVirtualMethod(TBitBtn, vmtNewInstance);
OrgTBitBtn_FreeInstance := GetVirtualMethod(TBitBtn, vmtFreeInstance);
SetVirtualMethod(Buttons.TBitBtn, vmtNewInstance, @TBitBtn_NewInstance);
SetVirtualMethod(Buttons.TBitBtn, vmtFreeInstance, @TBitBtn_FreeInstance);
end;
procedure RemoveHooks;
begin
SetVirtualMethod(Buttons.TBitBtn, vmtNewInstance, @OrgTBitBtn_NewInstance);
SetVirtualMethod(Buttons.TBitBtn, vmtFreeInstance, @OrgTBitBtn_FreeInstance);
end;
initialization
InstallHooks;
finalization
RemoveHooks;
end.
uses
このユニットをプログラムの任意の句に含めると、インスタンスBitBtnInstanceCounter
の数が追跡されます。TBitBtn
編集:複数のスレッドが同時に追跡クラスのオブジェクトを作成する可能性がある場合は、インターロックアクセスを使用してカウンター変数を変更する必要があります。SINGLE_THREAD
サードパーティのコンポーネントがサイレントにスレッドを使用する可能性があるため、シンボルを定義しない方が安全であることに注意してください。
于 2012-05-10T21:56:50.460 に答える
3
それを行うための組み込みの方法はありません。一部のプロファイラー(AQTime?)は、カスタムヒープマネージャーフックをインストールし、オブジェクトの先頭にある型ポインターを確認することで、このようなメトリックを生成します。これは自分で行うことができますが、これが開発中のプロファイリング用である場合は、他の人がすでに開発およびテストしたものを使用する方がはるかに簡単です。
于 2012-05-10T17:42:05.933 に答える