X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fshared%2Fxprofiler.pas;h=51d99e8b0e0e8fd155b8aa256add97d1fde688bd;hb=7d66e4504587cde0a3f9f3bbc0d48509a80c3056;hp=083704863848142f8e7f8342f3c57a260d1e9959;hpb=7869ee331ead2e3f765af47eeca1566ed97faa19;p=d2df-sdl.git diff --git a/src/shared/xprofiler.pas b/src/shared/xprofiler.pas index 0837048..51d99e8 100644 --- a/src/shared/xprofiler.pas +++ b/src/shared/xprofiler.pas @@ -15,6 +15,7 @@ *) // stopwatch timer to measure short periods (like frame rendering phases) {$INCLUDE a_modes.inc} +{.$DEFINE XPROFILER_SLOW_AVERAGE} unit xprofiler; interface @@ -69,22 +70,24 @@ type const - TProfHistorySize = 100; + TProfHistorySize = 1000; type TProfilerBar = record private - const FilterFadeoff = 0.05; // 5% + //const FilterFadeoff = 0.05; // 5% private - history: array [0..TProfHistorySize-1] of Integer; // circular buffer - hisHead: Integer; - curval: Single; + history: array of Integer; // circular buffer + hisLast: Integer; + //curval: Single; + curAccum: UInt64; + curAccumCount: Integer; mName: AnsiString; mLevel: Integer; private - procedure initialize (); inline; + procedure initialize (aHistSize: Integer); inline; function getvalue (): Integer; inline; function getvalat (idx: Integer): Integer; inline; function getcount (): Integer; inline; @@ -121,9 +124,10 @@ type public bars: array of TProfilerBar; // 0: total time name: AnsiString; + histSize: Integer; public - constructor Create (aName: AnsiString); + constructor Create (aName: AnsiString; aHistSize: Integer); destructor Destroy (); override; // call this on frame start @@ -267,44 +271,53 @@ end; // ////////////////////////////////////////////////////////////////////////// // -procedure TProfilerBar.initialize (); begin hisHead := -1; curval := 0; end; +procedure TProfilerBar.initialize (aHistSize: Integer); begin SetLength(history, aHistSize); hisLast := -1; curAccum := 0; curAccumCount := 0; end; procedure TProfilerBar.update (val: Integer); var idx: Integer; begin if (val < 0) then val := 0; //else if (val > 1000000) val := 1000000; - if (hisHead = -1) then begin hisHead := 0; curval := 0; for idx := 0 to TProfHistorySize-1 do history[idx] := val; end; - history[hisHead] := val; - Inc(hisHead); - if (hisHead = TProfHistorySize) then hisHead := 0; - curval := FilterFadeoff*val+(1.0-FilterFadeoff)*curval; + if (hisLast = -1) then begin hisLast := High(history); curAccum := 0; curAccumCount := 0; for idx := 0 to High(history) do history[idx] := val; end; + if (curAccumCount = Length(history)) then Dec(curAccum, UInt64(history[(hisLast+1) mod Length(history)])) else Inc(curAccumCount); + Inc(hisLast); + if (hisLast >= Length(history)) then hisLast := 0; + Inc(curAccum, UInt64(val)); + history[hisLast] := val; + //curval := FilterFadeoff*val+(1.0-FilterFadeoff)*curval; end; function TProfilerBar.getvalue (): Integer; -//var idx: Integer; +{$IFDEF XPROFILER_SLOW_AVERAGE} +var idx: Integer; +{$ENDIF} begin - result := round(curval); - { + {$IFDEF XPROFILER_SLOW_AVERAGE} result := 0; - for idx := 0 to TProfHistorySize-1 do Inc(result, history[idx]); - result := result div TProfHistorySize; - } + for idx := 0 to High(history) do Inc(result, history[idx]); + result := result div Length(history); + {$ELSE} + //result := round(curval); + if curAccumCount > 0 then result := Integer(curAccum div curAccumCount) else result := 0; + {$ENDIF} end; -function TProfilerBar.getcount (): Integer; begin result := TProfHistorySize; end; +function TProfilerBar.getcount (): Integer; begin result := Length(history); end; function TProfilerBar.getvalat (idx: Integer): Integer; begin - if (idx < 0) or (idx >= TProfHistorySize) then result := 0 else result := history[(hisHead-idx-1+TProfHistorySize*2) mod TProfHistorySize]; + if (idx < 0) or (idx >= Length(history)) then result := 0 else result := history[(hisLast-idx+Length(history)*2) mod Length(history)]; end; // ////////////////////////////////////////////////////////////////////////// // -constructor TProfiler.Create (aName: AnsiString); +constructor TProfiler.Create (aName: AnsiString; aHistSize: Integer); begin name := aName; bars := nil; + if (aHistSize < 10) then aHistSize := 10; + if (aHistSize > 10000) then aHistSize := 10000; + histSize := aHistSize; {$IF DEFINED(STOPWATCH_IS_HERE)} xptimer.clear(); xpsecs := nil; @@ -315,7 +328,10 @@ end; destructor TProfiler.Destroy (); +var + idx: Integer; begin + for idx := 0 to High(bars) do bars[idx].history := nil; bars := nil; {$IF DEFINED(STOPWATCH_IS_HERE)} xpsecs := nil; @@ -369,11 +385,11 @@ begin SetLength(bars, xpsused+1); for idx := 1 to xpsused do begin - bars[idx].initialize(); + bars[idx].initialize(histSize); bars[idx].mName := xpsecs[idx-1].name; bars[idx].mLevel := xpsecs[idx-1].level+1; end; - bars[0].initialize(); + bars[0].initialize(histSize); bars[0].mName := name; bars[0].mLevel := 0; end; @@ -392,7 +408,7 @@ begin if (length(bars) <> 1) then begin SetLength(bars, 1); - bars[0].initialize(); + bars[0].initialize(histSize); bars[0].mName := name; bars[0].mLevel := 0; end;