Page 32 of 35

Re: 7.2-Beta testers-thread

Posted: 07.12.2017, 00:21
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.3.x svn 4067:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.3/

compile and run on:

- Lazarus 1.8.0-Win32 (Windows 10-32),
- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

Michal

Re: 7.2-Beta testers-thread

Posted: 07.12.2017, 11:02
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.2.x svn 4068:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.2/

compile and run on:

- Lazarus 1.8.0-Win32 (Windows 10-32),
- Delphi 2007-Win32/C++32 (Windows 10-64),
- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

Michal

Re: 7.2-Beta testers-thread

Posted: 31.12.2017, 17:41
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.2.x svn 4080:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.2/

compile and run on:

- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

Michal

Re: 7.2-Beta testers-thread

Posted: 11.01.2018, 01:02
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.3.x svn 4077:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.3/

compile and run on:

- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

Michal

Re: 7.2-Beta testers-thread

Posted: 11.01.2018, 01:04
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.2.x svn 4081:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.2/

compile and run on:

- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

Michal

Re: 7.2-Beta testers-thread

Posted: 13.01.2018, 17:13
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.3.x svn 4087:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.3/

compile and run on:

- Lazarus 1.8.0-Win32 (Windows 10-32),
- Delphi 2007-Win32 (Windows 10-64),
- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

Michal

Re: 7.2-Beta testers-thread

Posted: 29.01.2018, 18:42
by miab3
@ Fr0sT, @EgonHugeist, @mdaems, @Jan, All

ZEOS 7.3.x svn 4109:
http://sourceforge.net/p/zeoslib/code-0 ... sting-7.3/

compile and run on:

- Lazarus 1.8.0-Win32 (Windows 10-32),
- Delphi 2007-Win32 (Windows 10-64),
- Delphi 10 Seattle-Win32/Win64 (Windows 10-64).

@Fr0sT: Version 4109 seems to be around 10% slower than 4087 !!!!

Michal

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 08:24
by Fr0sT
miab3 wrote:@Fr0sT: Version 4109 seems to be around 10% slower than 4087 !!!!
This says nothing... details?

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 11:36
by miab3
Fr0sT wrote:
miab3 wrote:@Fr0sT: Version 4109 seems to be around 10% slower than 4087 !!!!
This says nothing... details?
Slower (5%-20% - depending on the database) at multiple (thousands of times) reading / writing.
by. scheme:

Code: Select all

ZQuery1.First;   
while NOT ZQuery1.EOF do
     begin
     ZQuery1.Edit;
     ZQuery1.Fields[3].AsFloat:=ZQuery1.Fields[3].AsFloat+0.1;
     ZQuery1.Fields[4].AsString:=ZQuery1.Fields[4].AsString+'a';
     ZQuery1.Next;
     end;
Michal

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 12:14
by Fr0sT
That's better! I'll take a look

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 14:42
by Fr0sT
I don't see any significant slowdown.
FB 2.5, 4000 records, following loop:

Code: Select all

    while not ZQuery1.EOF do
    begin
      ZQuery1.Edit;
      ZQuery1.Fields[0].AsFloat:=ZQuery1.Fields[0].AsFloat+0.001;
      ZQuery1.Fields[1].AsString:=RandomString(10);
      ZQuery1.Post;
      ZQuery1.Next;
    end;
-4062-
13810
13750
13689
AVG: 13749,67

-4083-
12367
14321
14241
AVG: 13643,00

-4087-
13950
14230
14001
AVG: 14060,33

-4109-
13970
14441
13770
AVG: 14060,33

These 2% probably come from more universal query construction with identifier convertor.

Anyway such kind of loop is not a typical use case. If we enable CachedUpdates, the loop finishes in ~73 msecs so it is the query preparation/execution stuff that takes most of the time. And I doubt any good app has a dataset that generates 3.5 queries per second.

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 14:54
by EgonHugeist
@Frost

by now i can't see something except:
R4105 (internalGet/SetInt etc). What was the reason for that? Get a 1Byte Val as Param, push to a 4 byte val of internalSet() and finally push back to the 1Byte Val of memory address. But i'm not a compiler hero to judge if there is an performance loss, except all the nasty rangecheck and overflowchecks the compiler adds for such code simplification and doubled case Type of: checks, of course.
Note not allways a few lines of code my be fast.. Those lines seem to be duplicate code but it wasn't such one. I vote for rollback and add comments instead. Do you agree?

Any other ideas?

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 17:46
by Fr0sT
Michael, the reason is to avoid code duplication. For me, it is much larger evil than slight performance loss (if it truly exists!) because changes to this code copies become a nightmare.
Regarding the code, I checked ASM and there's no difference between 1-byte and 4-byte values. CPU registers are integer-sized anyway so any smaller value is widened when moving to/from memory. Overflow checks are disabled by compiler directive. So I see no reasons to revert.
I even benchmarked this: old SetWord and new SetByte. Results are: ~5800 msecs vs ~6700 msecs on 100000000 (100M!) iterations. 10 microseconds lost per iteration. And I'm more than sure this lag is caused by function call (I tested on D7 where there's no inlining). With inlining I'm sure the performance will be the same.

BTW, string clearing in the function's epilogue has even larger performance impact. This modification

Code: Select all

procedure TZRowAccessor.InternalSetInt(ColumnIndex, Value: Integer);
var
  Data: PPointer;

  procedure  SetStr(ColumnIndex, Value: Integer);
  begin
    if Self is TZRawRowAccessor
        then SetRawByteString(ColumnIndex, IntToRaw(Value))
        else SetUnicodeString(ColumnIndex, IntToUnicode(Value));
  end;

begin
  {$R-}
  FBuffer.Columns[FColumnOffsets[ColumnIndex{$IFNDEF GENERIC_INDEX} - 1{$ENDIF}]] := bIsNotNull;
  Data := @FBuffer.Columns[FColumnOffsets[ColumnIndex{$IFNDEF GENERIC_INDEX} - 1{$ENDIF}] + 1];
  {$IFDEF RangeCheckEnabled}{$R+}{$ENDIF}
  case FColumnTypes[ColumnIndex{$IFNDEF GENERIC_INDEX} - 1{$ENDIF}] of
    ...
    stString, stUnicodeString:
      SetStr(ColumnIndex, Value);
  end;
end;
gives ~4200 msec time for new SetByte (faster than old SetWord even without inlining!) assuming that setting int values to string fields is rare.

Re: 7.2-Beta testers-thread

Posted: 30.01.2018, 18:02
by EgonHugeist
Nice to know.
AFAIR Compilers do align the stack to a value x and smallest memblock as well. Thanks for the findings so let's keep it as is an track what Miab3 did report.
In addition what's the cost of

Code: Select all

 if Self is TZRawRowAccessor
        then SetRawByteString(ColumnIndex, IntToRaw(Value))
        else SetUnicodeString(ColumnIndex, IntToUnicode(Value));
 
against

Code: Select all

  if (Consettings.ClientCodePage.Encoding= zCP_ceUTF16) or not Consettings.ClientCodePage.IsStringFieldCPConsistent 
  then SetUnicodeString(ColumnIndex, IntToUnicode(Value))
  else SetRawByteString(ColumnIndex, IntToRaw(Value));
 
IF secondary code would win the challange i would kill my introduced TZ(Raw/Unicode)RowAccessor and simply use one.. IF this is understandable for others of course...

Re: 7.2-Beta testers-thread

Posted: 31.01.2018, 09:10
by Fr0sT
EgonHugeist wrote:In addition what's the cost of ...
Well in this case it's hard to benchmark exactly these pieces but I tried with other classes (var obj: TBaseClass, TDescClass = class(TBaseClass), condition "if obj is TDescClass") and this variant happens to be 10 times slower: 178062 ops/sec vs 1602564 ops/sec for the one you suggested. Moreover, ideologically it is always a non-recommended option to mention descendant classes in parent one. On the other hand, modified condition lacks plainness of previous variant. I suggest the compromise:

Code: Select all

  TZRowAccessor = class(TObject)
  protected
    FIsRaw: Boolean;
  ...
  end;

  TZRawRowAccessor.Create()
  begin
     FIsRaw := True;
  end;
  
  ...
  
  if Self.FIsRaw
        then SetRawByteString(ColumnIndex, IntToRaw(Value))
        else SetUnicodeString(ColumnIndex, IntToUnicode(Value));
This variant gives 1.8 times better perf compared to ConSettings comparisons (2714440 / 1512401 ops/sec) and still is pretty clear.
Anyway. We're talking about hundreds of thousands ops per sec. The slowdown Michal has noticed is of a much larger scale though I'm still sceptical. Query execution takes ~100-200 msecs inside DB engine, all our performance tricks are nothing compared to this delay.

So. To realize what's going on I'd ask for a sample project. As I said before, I see no meaningful regressions in my environment.

P.S. I've run test project under AQTime. Of overall 3*9=27 seconds test time, TZFirebirdBaseDriver::isc_dsql_execute consumes 10.222 and TZFirebirdBaseDriver::isc_commit_retaining takes 16.367. :mrgreen: