Re: YANFCQ [Yet Another Non-FastCode Question]: TDateTime -> uSec resolution



On Wed, 27 Jul 2005 00:30:13 +0200, "Kristofer Skaug"
<nospam@xxxxxxxxx> wrote:

>This is the "dumbest thing that could possibly work", but I wouldn't be
>posting this if I wasn't looking for better performance.

Hmm, I found that it's not correct in all cases. For instance, try
passing it 1 - 1 / UsecsPerDay, ie one usec before midnight. The
integer approach is more correct, although the naive delphi version is
slower:

procedure DecodeTimeUsec2(const ATime: TDateTime; out
hh, mm, ss, USecs: LongWord);
var
RestTime: int64; // does this help? not sure
begin
RestTime:= round(Frac(ATime) * USecsPerDay);

ss:= RestTime div 1000000;
USecs:= RestTime - int64(ss) * 1000000;

mm:= ss div 60;
ss:= ss - mm * 60;

hh:= mm div 60;
mm:= mm - hh * 60;
end;

However this rather quick conversion to asm does indeed speed things
up. On my box it's about 3x faster, and 2x faster than your original
version. I bet it could be even faster, but I just couldn't be
bothered right now :D

procedure DecodeTimeUsec4(const ATime: TDateTime; out
hh, mm, ss, USecs: LongWord);
const
usd: int64 = UsecsPerDay;
var
RestTime: int64;
ocw, ncw: word;
asm
push ebx
push esi
push edi

mov ebx, eax
mov esi, edx
mov edi, ecx

//RestTime:= round(Frac(ATime) * USecsPerDay);
fnstcw word ptr [ocw]
fld qword ptr [ebp+12]
fnstcw word ptr [ncw]
fld st(0)
or word ptr [ncw], $0F00 // trunc toward zero, full precision
fldcw word ptr [ncw]
frndint
fldcw word ptr [ocw]

fsub

fild qword ptr [usd]
fmulp
fistp qword ptr [RestTime]

mov ecx, 1000000
mov eax, dword ptr [RestTime]
mov edx, dword ptr [RestTime+4]

div ecx

mov ecx, dword ptr [ebp+8]
mov dword ptr [ecx], edx

mov ecx, 60
xor edx, edx
div ecx
mov dword ptr [edi], edx

xor edx, edx
div ecx
mov dword ptr [esi], edx
mov dword ptr [ebx], eax

pop edi
pop esi
pop ebx
end;

Cheers

- Asbjørn

.



Relevant Pages