#1 2017-07-11 11:01:16

RObyDP
Member
Registered: 2015-02-19
Posts: 62

Asm PosBinary function please

hello Arnaud,

do you have a fast ASM function to do a Pos with mem pointers or array of bytes instead of strings? ( I want avoid the @uniquestring call each time Pcasting)
For 64bit of course

for example should be PosBin(SubStr:TBytes; Source: Pointer; Index:UInt64);

I can do in pascal using memcompare and indexes, but I know your crew is strong with ASM

let me know
thank you
Roberto

Offline

#2 2017-07-11 12:41:54

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Asm PosBinary function please

Shouldn't Source be a TBytes too?

Under x86/Win32 you can just reuse the PosEx() asm in SynCommons, and change the function declaration:

function PosBin(const SubStr, Source: TBytes; Offset: integer = 1): Integer;
asm 
        push    ebx
        push    esi
        push    edx
        test    eax, eax
  ...

In fact, at least under x86, AnsiString and TBytes do have the same memory layout (if I remember correctly).

Under x64, I don't have asm at hand.
My guess is that two nested loops will be faster than calling CompareMem().
You may try this:

function PosBin(const SubStr, S: TBytes; Offset: PtrUInt = 1): Integer;
var len, lenSub: PtrInt;
    ch: AnsiChar;
    p, pSub, pStart, pStop: PAnsiChar;
label Loop0, Loop4, TestT, Test0, Test1, Test2, Test3, Test4,
      AfterTestT, AfterTest0, Ret, Exit;
begin;
  pSub := pointer(SubStr);
  p := pointer(S);
  if (p=nil) or (pSub=nil) or (Offset<1) then begin
    Result := 0;
    goto Exit;
  end;
  len := PDynArrayRec(Pointer(PtrInt(p)-STRRECSIZE))^.length;
  lenSub := PDynArrayRec(Pointer(PtrInt(pSub)-STRRECSIZE))^.length-1;
  if (len<lenSub+PtrInt(Offset)) or (lenSub<0) then begin
    Result := 0;
    goto Exit;
  end;
  pStop := p+len;
  p := p+lenSub;
  pSub := pSub+lenSub;
  pStart := p;
  p := p+Offset+3;
  ch := pSub[0];
  lenSub := -lenSub;
  if p<pStop then goto Loop4;
  p := p-4;
  goto Loop0;
Loop4:
  if ch=p[-4] then goto Test4;
  if ch=p[-3] then goto Test3;
  if ch=p[-2] then goto Test2;
  if ch=p[-1] then goto Test1;
Loop0:
  if ch=p[0] then goto Test0;
AfterTest0:
  if ch=p[1] then goto TestT;
AfterTestT:
  p := p+6;
  if p<pStop then goto Loop4;
  p := p-4;
  if p<pStop then goto Loop0;
  Result := 0;
  goto Exit;
Test3: p := p-2;
Test1: p := p-2;
TestT: len := lenSub;
  if lenSub<>0 then
  repeat
    if (psub[len]<>p[len+1]) or (psub[len+1]<>p[len+2]) then
      goto AfterTestT;
    len := len+2;
  until len>=0;
  p := p+2;
  if p<=pStop then goto Ret;
  Result := 0;
  goto Exit;
Test4: p := p-2;
Test2: p := p-2;
Test0: len := lenSub;
  if lenSub<>0 then
  repeat
    if (psub[len]<>p[len]) or (psub[len+1]<>p[len+1]) then
      goto AfterTest0;
    len := len+2;
  until len>=0;
  inc(p);
Ret:
  Result := p-pStart;
Exit:
end;

Offline

#3 2017-07-11 14:37:09

RObyDP
Member
Registered: 2015-02-19
Posts: 62

Re: Asm PosBinary function please

very thanks

Offline

#4 2017-07-11 14:55:44

RObyDP
Member
Registered: 2015-02-19
Posts: 62

Re: Asm PosBinary function please

can I ask a courtesy?

Do you have tested this MM https://github.com/d-mozulyov/BrainMM ?

Will be nice see how it performs into a real life benchmark using the mormot multithreaded test...

I want see if it really scale so well, and the reliability.

Offline

#5 2017-07-12 08:13:32

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: Asm PosBinary function please

I didn't test it yet.
Source code is nice - I like the single-unit approach.
Some design details (e.g. bit-based allocation instead of linked lists) is told to reduce memory consumption.
May be worth looking at in testing, perhaps not (yet) on production.

Anyway, we tried to avoid as much memory allocation as possible in mORMot units, so in practice, a good fast memory manager like FastMM4 gives good results, even on multi-threaded process.

Offline

Board footer

Powered by FluxBB