|
|
@@ -5,7 +5,6 @@ unit uutlEmbeddedProfiler; |
|
|
|
{$OPTIMIZATION REGVAR} |
|
|
|
{$OPTIMIZATION PEEPHOLE} |
|
|
|
{$OPTIMIZATION CSE} |
|
|
|
{$OPTIMIZATION ASMCSE} |
|
|
|
|
|
|
|
interface |
|
|
|
|
|
|
@@ -26,17 +25,11 @@ implementation |
|
|
|
{$IFDEF PROFILER_ENABLE} |
|
|
|
|
|
|
|
uses |
|
|
|
Windows, lineinfo{%H-}, Classes, fgl, unFastFileStream; |
|
|
|
Windows, Classes, unFastFileStream; |
|
|
|
|
|
|
|
type |
|
|
|
TWriterThread = class(TThread) |
|
|
|
private type |
|
|
|
TCacheEntry = record |
|
|
|
Name, Src: ShortString; Line: integer; |
|
|
|
end; |
|
|
|
TCacheList = specialize TFPGMap<PtrUInt, TCacheEntry>; |
|
|
|
private |
|
|
|
fAddressCache: TCacheList; |
|
|
|
fPF: Int64; |
|
|
|
procedure SaveCurrentWrite; |
|
|
|
public |
|
|
@@ -56,16 +49,18 @@ type |
|
|
|
TProfileDataFile = class |
|
|
|
public |
|
|
|
constructor Create(const {%H-}aFileName: string); |
|
|
|
procedure WriteEnter(Thread: TThreadID; When: Int64; Func, Src: String; Line: Integer); virtual; abstract; |
|
|
|
procedure WriteEnter(Thread: TThreadID; When: Int64; Func: PtrUInt; Name: string); virtual; abstract; |
|
|
|
procedure WriteLeave(Thread: TThreadID; When: Int64); virtual; abstract; |
|
|
|
end; |
|
|
|
|
|
|
|
{$DEFINE __HEAD} |
|
|
|
//{$I uutlProfilerPlainText.inc} |
|
|
|
{$I uutlProfilerPlainTextMMap.inc} |
|
|
|
{$I uutlProfilerBinary.inc} |
|
|
|
//{$I uutlProfilerPlainTextMMap.inc} |
|
|
|
{$UnDef __HEAD} |
|
|
|
//{$I uutlProfilerPlainText.inc} |
|
|
|
{$I uutlProfilerPlainTextMMap.inc} |
|
|
|
{$I uutlProfilerBinary.inc} |
|
|
|
//{$I uutlProfilerPlainTextMMap.inc} |
|
|
|
|
|
|
|
|
|
|
|
const |
|
|
@@ -122,20 +117,6 @@ begin |
|
|
|
inc(LineNumberComp); |
|
|
|
end; |
|
|
|
|
|
|
|
procedure TestDebugInfoPresent; |
|
|
|
var |
|
|
|
f,s: ShortString; |
|
|
|
l: LongInt; |
|
|
|
begin |
|
|
|
f:= ''; |
|
|
|
s:= ''; |
|
|
|
l:= 0; |
|
|
|
if not GetLineInfo({%H-}PtrUInt(@TestDebugInfoPresent),f,s,l) then begin |
|
|
|
raise Exception.Create('Profiler is enabled, but no suitable debug info could be found.'); |
|
|
|
Halt(); |
|
|
|
end; |
|
|
|
end; |
|
|
|
|
|
|
|
procedure ProfilerEnterProc(const Addr: Pointer); |
|
|
|
begin |
|
|
|
ProfilerEnterProc(Addr, ''); |
|
|
@@ -206,14 +187,11 @@ end; |
|
|
|
constructor TWriterThread.Create; |
|
|
|
begin |
|
|
|
inherited Create(false); |
|
|
|
fAddressCache:= TCacheList.Create; |
|
|
|
fAddressCache.Sorted:= true; |
|
|
|
QueryPerformanceFrequency(fPF); |
|
|
|
end; |
|
|
|
|
|
|
|
destructor TWriterThread.Destroy; |
|
|
|
begin |
|
|
|
FreeAndNil(fAddressCache); |
|
|
|
inherited Destroy; |
|
|
|
end; |
|
|
|
|
|
|
@@ -239,7 +217,6 @@ end; |
|
|
|
|
|
|
|
procedure TWriterThread.SaveCurrentWrite; |
|
|
|
var |
|
|
|
ce: TCacheEntry; |
|
|
|
i: integer; |
|
|
|
begin |
|
|
|
if Events[WritePtr].Func = 0 then |
|
|
@@ -247,19 +224,7 @@ begin |
|
|
|
if Events[WritePtr].Func = RETURN_FUNCTION then |
|
|
|
ProfilerDataFile.WriteLeave(Events[WritePtr].Thread, (Events[WritePtr].When * 1000 * 1000) div fPF) |
|
|
|
else begin |
|
|
|
i:= fAddressCache.IndexOf(Events[WritePtr].Func); |
|
|
|
if i < 0 then begin |
|
|
|
ce.Line:= 0; |
|
|
|
ce.Src:= ''; |
|
|
|
GetLineInfo(Events[WritePtr].Func,ce.Name,ce.Src,ce.Line); |
|
|
|
if (ce.Name = '') then |
|
|
|
ce.Name := Format('0x%.16x', [Events[WritePtr].Func]); |
|
|
|
fAddressCache.Add(Events[WritePtr].Func, ce); |
|
|
|
end else |
|
|
|
ce:= fAddressCache.Data[i]; |
|
|
|
if (Events[WritePtr].Name <> '') then |
|
|
|
ce.Name := '[' + Events[WritePtr].Name + '] ' + ce.Name; |
|
|
|
ProfilerDataFile.WriteEnter(Events[WritePtr].Thread, (Events[WritePtr].When * 1000 * 1000) div fPF, ce.Name, ce.Src, ce.Line); |
|
|
|
ProfilerDataFile.WriteEnter(Events[WritePtr].Thread, (Events[WritePtr].When * 1000 * 1000) div fPF, Events[WritePtr].Func, Events[WritePtr].Name); |
|
|
|
end; |
|
|
|
Events[WritePtr].Func:= 0; |
|
|
|
end; |
|
|
@@ -284,10 +249,9 @@ initialization |
|
|
|
WritePtr:= 0; |
|
|
|
WriterThread:= nil; |
|
|
|
CalibrateLineNumberCompensation; |
|
|
|
TestDebugInfoPresent; |
|
|
|
//ProfilerDataFile:= TProfilePlainText.Create(ChangeFileExt(ParamStr(0), '.profraw')); |
|
|
|
//ProfilerDataFile:= TProfileBinary.Create(ChangeFileExt(ParamStr(0), '.profbin')); |
|
|
|
ProfilerDataFile:= TProfilePlainTextMMap.Create(ChangeFileExt(ParamStr(0), '.profraw')); |
|
|
|
ProfilerDataFile:= TProfileBinary.Create(ChangeFileExt(ParamStr(0), '.profbin')); |
|
|
|
//ProfilerDataFile:= TProfilePlainTextMMap.Create(ChangeFileExt(ParamStr(0), '.profraw')); |
|
|
|
ProfilerEnabled:= true; |
|
|
|
{$ENDIF} |
|
|
|
|
|
|
|