To Delphi Seatle alter to:
procedure TForm1.PreparaRegistrosDA;
begin
DARemoteDataAdapter1.DataStreamer := DABin2DataStreamer1;
DAMemDataTable1.RemoteDataAdapter := DARemoteDataAdapter1;
DAMemDataTable1.RemoteFetchEnabled := False;
I’ve created console version of your testcase and tested it with DA9 and different versions of delphi.
as you can see from my tests, different versions of Delphi give different results so I think, something inside delphi (i.e. DB.pas) was changed.
non-unicode versions of Delphi give better results, later XE versions have worse time, Delphi 10.* have better optimization in comparing with XE:
Compiler version is 15 (Delphi 7)
410 milisegundos - Nulos:405799 without BusinessRulesID
668 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 321 milisegundos - edit without BusinessRulesID
6 segundos 873 milisegundos - edit with BusinessRulesID
Compiler version is 18 (Delphi 2007)
454 milisegundos - Nulos:405799 without BusinessRulesID
782 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 536 milisegundos - edit without BusinessRulesID
8 segundos 160 milisegundos - edit with BusinessRulesID
Compiler version is 21 (Delphi 2010)
400 milisegundos - Nulos:405799 without BusinessRulesID
694 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 28 milisegundos - edit without BusinessRulesID
7 segundos 160 milisegundos - edit with BusinessRulesID
Compiler version is 23 (XE2)
505 milisegundos - Nulos:405799 without BusinessRulesID
995 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 8 milisegundos - edit without BusinessRulesID
10 segundos 47 milisegundos - edit with BusinessRulesID
Compiler version is 26 (XE5)
720 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 416 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 761 milisegundos - edit without BusinessRulesID
13 segundos 952 milisegundos - edit with BusinessRulesID
Compiler version is 28 (XE7)
710 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 413 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 726 milisegundos - edit without BusinessRulesID
13 segundos 846 milisegundos - edit with BusinessRulesID
Compiler version is 30 (Delphi 10 Seattle)
533 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 115 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 381 milisegundos - edit without BusinessRulesID
11 segundos 455 milisegundos - edit with BusinessRulesID
Compiler version is 31 (Delphi 10.1 Berlin)
537 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 122 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 381 milisegundos - edit without BusinessRulesID
11 segundos 524 milisegundos - edit with BusinessRulesID
the problem with TBOtbl_duprec_com_parc.OnCalcFields. it’s a quite slow method and fired when every field is modified.
I can recommend to use Enable*/Disable* methods like DisableEventHandlers/EnableEventHandlers for batch operations.
in this case, I’ve got these results:
Compiler version is 28
710 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 402 milisegundos - Nulos:319562 with BusinessRulesID
1 segundo 574 milisegundos - edit without BusinessRulesID
1 segundo 573 milisegundos - edit with BusinessRulesID
of cource, in some cases this solution isn’t accepted.
Thank you for advice, but,
in this case, that the calculed fields are useds to validate in beforepost and to get values to other objects, so, isn´t accepted.
And In his view there is a possibility to return to speed in delphi 7 levels?
the same DA code and the same PC was used for these tests.
one difference was - different versions of delphi was used for compiling.
the problem in your OnCalcField event - it slows entire progress:
Compiler version is 28
706 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 404 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 770 milisegundos - edit without BusinessRulesID
13 segundos 876 milisegundos - edit with BusinessRulesID
RecordCount is 9568
OnCalcField was fired 184707 times
CASE 1 - set the eleven calculated fields to 0 with "strongly typed"
Compiler version is 30
654 milisegundos - Nulos:405799 without BusinessRulesID
1088 milisegundos - Nulos:300551 with BusinessRulesID
3952 milisegundos - edit without BusinessRulesID
8325 milisegundos - edit with BusinessRulesID
Compiler version is 18
374 milisegundos - Nulos:405799 without BusinessRulesID
437 milisegundos - Nulos:300551 with BusinessRulesID
2312 milisegundos - edit without BusinessRulesID
3016 milisegundos - edit with BusinessRulesID CASE 2 - set the eleven calculated fields to 0 with fieldbyname
Compiler version is 30
654 milisegundos - Nulos:405799 without BusinessRulesID
1111 milisegundos - Nulos:300551 with BusinessRulesID
3960 milisegundos - edit without BusinessRulesID
8880 milisegundos - edit with BusinessRulesID
Compiler version is 18
375 milisegundos - Nulos:405799 without BusinessRulesID
671 milisegundos - Nulos:300551 with BusinessRulesID
2311 milisegundos - edit without BusinessRulesID
7422 milisegundos - edit with BusinessRulesID CASE 3 - set the eleven calculated fields to other field with "strongly typed"
Compiler version is 30
651 milisegundos - Nulos:405799 without BusinessRulesID
1353 milisegundos - Nulos:300551 with BusinessRulesID
3958 milisegundos - edit without BusinessRulesID
13196 milisegundos - edit with BusinessRulesID
Compiler version is 18
360 milisegundos - Nulos:405799 without BusinessRulesID
514 milisegundos - Nulos:300551 with BusinessRulesID
2250 milisegundos - edit without BusinessRulesID
3827 milisegundos - edit with BusinessRulesID CASE 4 - CalcFields original
Compiler version is 30
650 milisegundos - Nulos:405799 without BusinessRulesID
1335 milisegundos - Nulos:319562 with BusinessRulesID
3918 milisegundos - edit without BusinessRulesID
14007 milisegundos - edit with BusinessRulesID
Compiler version is 18
360 milisegundos - Nulos:405799 without BusinessRulesID
485 milisegundos - Nulos:319562 with BusinessRulesID
2203 milisegundos - edit without BusinessRulesID
4265 milisegundos - edit with BusinessRulesID
Code:
CASE 1 - set the eleven calculated fields to 0 with "strongly typed"
procedure TBOtbl_duprec_com_parc.OnCalcFields(DataTable: TDADataTable);
begin
inherited;
recp_valorAddTxEmiss:=0;
Diferenca := 0;
DiasEmAtraso := 0;
recpDlrIndice := 0;
recpDlrPgto := 0;
JuroPago_Pc_Mes := 0;
SituacaoPrazo := ‘’;
VlrComJuros:= 0;
Venc_Ano := 0;
Venc_Mes := 0;
PrazoEmDias := 0;
end;
CASE 2 - set the eleven calculated fields to 0 with fieldbyname
procedure TBOtbl_duprec_com_parc.OnCalcFields(DataTable: TDADataTable);
begin
inherited;
DataTable.Dataset.FieldByName(‘recp_valorAddTxEmiss’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘Diferenca’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘DiasEmAtraso’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘recpDlrIndice’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘recpDlrPgto’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘JuroPago_Pc_Mes’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘SituacaoPrazo’).AsString := ‘’;
DataTable.Dataset.FieldByName(‘VlrComJuros’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘Venc_Ano’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘Venc_Mes’).AsCurrency := 0;
DataTable.Dataset.FieldByName(‘PrazoEmDias’).AsCurrency := 0;
end;
CASE 3 - set the eleven calculated fields to other field with "strongly typed"
procedure TBOtbl_duprec_com_parc.OnCalcFields(DataTable: TDADataTable);
begin
inherited;
recp_valorAddTxEmiss:=recp_valor+recp_vlr_outros_acres;
Diferenca := recp_pgto_vlr - recp_valorAddTxEmiss;
DiasEmAtraso := Trunc(date-recp_dt_vencimento);
recpDlrIndice := recp_valor / 2;
recpDlrPgto := (recp_pgto_vlr/2)*recp_dlr_valor;
JuroPago_Pc_Mes := Diferenca;
SituacaoPrazo := ‘RECEBIDO’;
VlrComJuros:= recp_vlr_outros_acres;
Venc_Ano := StrToInt(FormatDateTime(‘yyyy’,recp_dt_vencimento));
Venc_Mes := StrToInt(FormatDateTime(‘mm’,recp_dt_vencimento));
PrazoEmDias := Trunc(recp_dt_vencimento-rec_dt_emiss);
end;
The Question
The datatable has 11 calculated fields, the simple fact of defining these fields doubles the time.
CASE 3 only set values.
Optimize for you is drop the code?
you can define these caclulated fields as usual fields (i.e. non-calculated) with LogChanges := False.
SQL can be like
SELECT
... ,
0 as Venc_Ano,
0 as Venc_Mes,
...
FROM ....
and calculate these fields only when it is needed, i.e. DiasEmAtraso, Venc_Ano and Venc_Mes can be calculated only when recp_dt_vencimento is changed
of course, some initial calculation can be required at opening table, but it will more faster because it will be calculated once per record instead of once per changed field.
Compiler version is 32 (Tokio)
532 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 50 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 208 milisegundos - edit without BusinessRulesID
10 segundos 905 milisegundos - edit with BusinessRulesID
Compiler version is 18 (D2007)
263 milisegundos - Nulos:405799 without BusinessRulesID
348 milisegundos - Nulos:319562 with BusinessRulesID
1 segundo 921 milisegundos - edit without BusinessRulesID
3 segundos 311 milisegundos - edit with BusinessRulesID
(Tokio) 532 milisegundos - Nulos:405799 without BusinessRulesID
(D2007) 263 milisegundos - Nulos:405799 without BusinessRulesID
(Tokio) 1 segundo 50 milisegundos - Nulos:319562 with BusinessRulesID
(D2007) 348 milisegundos - Nulos:319562 with BusinessRulesID
(Tokio) 3 segundos 208 milisegundos - edit without BusinessRulesID
(D2007) 1 segundo 921 milisegundos - edit without BusinessRulesID
(Tokio) 10 segundos 905 milisegundos - edit with BusinessRulesID
(D2007) 3 segundos 311 milisegundos - edit with BusinessRulesID
Compiler version is 30
521 milisegundos - Nulos:405799 without BusinessRulesID
1 segundo 60 milisegundos - Nulos:319562 with BusinessRulesID
3 segundos 230 milisegundos - edit without BusinessRulesID
11 segundos 48 milisegundos - edit with BusinessRulesID
function TDAMemoryDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
…
if not IsReferencedField(Field.DataType) then begin
Move(Data^, Buffer^, FDataSizeArray[Field.Index])
procedure TDAMemoryDataset.DataConvert(Field: TField; Source,
Dest: Pointer; ToNative: Boolean);
…
Case Field.Datatype of
ftBCD: PCurrency(Dest)^ := PCurrency(Source)^;
function TDAMemoryDataset.GetFieldData(Field: TField;{$IFDEF DELPHIXE4UP}var{$ENDIF} Buffer: Dataset_TValueBuffer): Boolean;
begin
Result := intGetFieldData(Field, Buffer);
end;
function TDAMemoryDataset.intGetFieldData(Field: TField;{$IFDEF DELPHIXE4UP}var{$ENDIF} Buffer: Dataset_TValueBuffer): Boolean;
…
{$ENDIF DA_FixedWideCharSupport}
else
Move(Data^, lbuf^, FDataSizeArray[i])
…
if Result and (FDataTypeArray[i] = ftBCD) then begin
CurrToBCD(PCurrency(lbuf)^, TBCD(lbuf^), 32, FFieldSizeArray[i]);
/////////////////////////////////////////////////// comparativo
In d2007 GetFieldData->Move->DataConvert
ftBCD: PCurrency(Dest)^ := PCurrency(Source)^;
In xe GetFieldData->intGetFieldData->
Move(Data^, lbuf^, FDataSizeArray[i])
if Result and (FDataTypeArray[i] = ftBCD) then begin
CurrToBCD(PCurrency(lbuf)^, TBCD(lbuf^), 32, FFieldSizeArray[i]);