Poslední příspěvky

Stran: 1 ... 8 9 [10]
91
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Delfin kdy 06-04-2018, 19:00:42 »
Tady je ukazka (samozrejme musis pouzit navrzeny fix pro korektni predani handle kontextu finalizacniho callbacku o kterem jsem psal par prispevku nazpet). Promenna StepCtx pak bude pri finalizaci obsahovat kontext handle krokoveho callbacku (ktery pouzivas jako klic ve svem dictionary):

Kód: Delphi [Vybrat]
  1. uses
  2.   FireDAC.Phys.SQLiteCli;
  3.  
  4. procedure TForm1.FDSQLiteFunction1Calculate(AFunc: TSQLiteFunctionInstance; AInputs: TSQLiteInputs;
  5.   AOutput: TSQLiteOutput; var AUserData: TObject);
  6. var
  7.   DataCtx: Pointer;
  8.   StepCtx: psqlite3_context;
  9. begin
  10.   StepCtx := AOutput.Handle;
  11.   DataCtx := sqlite3_aggregate_context(AOutput.Handle, SizeOf(NativeUInt));
  12.   if Assigned(DataCtx) then
  13.     PNativeUInt(DataCtx)^ := NativeUInt(StepCtx);
  14. end;
  15.  
  16. procedure TForm1.FDSQLiteFunction1Finalize(AFunc: TSQLiteFunctionInstance; var AUserData: TObject);
  17. var
  18.   DataCtx: Pointer;
  19.   StepCtx: psqlite3_context;
  20. begin
  21.   StepCtx := nil;
  22.   DataCtx := sqlite3_aggregate_context(AFunc.Output.Handle, 0);
  23.   if Assigned(DataCtx) then
  24.     StepCtx := psqlite3_context(DataCtx^);
  25. end;
92
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Delfin kdy 06-04-2018, 16:28:26 »
Za priradovanim handle-rov okamzite nasleduje DoFinalize, kde vystupoval povodny krokovy handle, takze je velmi pravdepodobne, ze tie volania budu OK, pretoze ja uchovavam povodny krokovy handle do HandleOld. Tak, ako by sa tvoja uprava kvazi nepouzila.

Tebou navrhovane reseni nebude fungovat. Poradi volani je pro 2 zaznamy nasledujici:

Kód: Delphi [Vybrat]
  1. OnCalculate - MojTotal(pole1)
  2. OnCalculate - MojTotal(pole2)
  3. OnCalculate - MojTotal(pole1)
  4. OnCalculate - MojTotal(pole2)
  5. OnFinalize - MojTotal(pole1)
  6. OnFinalize - MojTotal(pole2)

Ty bys tedy ve finalizaci MojTotal(pole1) zalohoval kontext handle kroku MojTotal(pole2).
93
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Miroslav Baláž kdy 06-04-2018, 16:10:35 »
Skusim to spravit ako navrhujes. Zda sa to rozumne..

Ale teraz si uvedomujem, ze moj HandleOld prebera povodny krokovy handle, tesne pred tou tebou navrhnutou upravou (bez ktorej aggregate nefunguje). Za priradovanim handle-rov okamzite nasleduje DoFinalize, kde vystupoval povodny krokovy handle, takze je velmi pravdepodobne, ze tie volania budu OK, pretoze ja uchovavam povodny krokovy handle do HandleOld. Tak, ako by sa tvoja uprava kvazi nepouzila.
94
Obecné / Re:Násobenie čísla, nie výrazu, jednotkou.
« Poslední příspěvek od vandrovnik kdy 06-04-2018, 16:05:59 »
No, nedalo mi to :-) Musím říct, že některé výsledky mě docela překvapily - třeba že single není rychlejší než double a že single víceméně stejně rychlý jako nativní integer, natož jak dopadne, když si člověk nenastaví EXCESSEXPRESSION OFF... (Hádám, že pokud by se měly např. počítat goniometrické funkce, tak by už single rychlejší bylo.) To měření času není moc přesné, i když se ve správci úloh nastaví priorita Reálný čas, stejně výsledky dost lítají. Testováno na obstarožním i7 920 @ 2,67 GHz, Win 10 64bit.

-----------

32bit app, uint32,
x:=12345678; y:=1; -------> 13957016
x:=12345678; y:=87654321; -------> 13998208

32bit app, uint64,
x:=1234567812345678; y:=1; -------> 35580995
x:=1234567812345678; y:=8765432187654321; -------> 35651912

32bit app, single,
x:=1234.5678; y:=1; -------> 14020182
x:=1234.5678; y:=8765.4321; -------> 14016425

32bit app, double,
x:=1234.5678; y:=1; -------> 12151941
x:=1234.5678; y:=8765.4321; -------> 12156582

------------

64bit app, uint32,
x:=12345678; y:=1; -------> 13163029
x:=12345678; y:=87654321; -------> 13419768

64bit app, uint64,
x:=1234567812345678; y:=1; -------> 13330492
x:=1234567812345678; y:=8765432187654321; -------> 13453193

64bit app, single, {$EXCESSPRECISION OFF}:
x:=1234.5678; y:=1; -------> 12677965
x:=1234.5678; y:=8765.4321; -------> 13731444

64bit app, single, {$EXCESSPRECISION ON}, popř. {$EXCESSPRECISION... ručně nenastaveno:
x:=1234.5678; y:=1; -------> 22079486
x:=1234.5678; y:=8765.4321; -------> 22047472

64bit app, double, {$EXCESSPRECISION OFF}:
x:=1234.5678; y:=1; -------> 14053849
x:=1234.5678; y:=8765.4321; -------> 14060714

64bit app, double, {$EXCESSPRECISION ON}, popř. {$EXCESSPRECISION... ručně nenastaveno:
x:=1234.5678; y:=1; -------> 14023874
x:=1234.5678; y:=8765.4321; -------> 14024711
95
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Delfin kdy 06-04-2018, 15:36:19 »
Ukazka by sa hodila.

Pripravim behem dne. Mam ted nejakou praci. Napad je pouzit agregacni kontext pro predani krokoveho kontext handle. V krokovem callbacku alokujes blok o velikosti sqlite3_context a ulozis do nej krokovy kontext handle. V dictionary ulozis ten samy handle a pocitas. No a ve finalizacnim callbacku si vyptas ten blok dat s krokovym kontext handle, najdes v dictionary vysledek a ten predas.

Ja som pre vyhladanie v dictionary (ta sa naplna pri krokovom prechadzani) vyuzil tuto konstrukciu:
Kód: Delphi [Vybrat]
  1. procedure TSQLiteFunctionInstance.DoFinalize(context: psqlite3_context);
  2. begin
  3.   FOutput.HandleOld := FOutput.Handle; // Miro doplnene HandleOld  6.4.2017
  4.   FOutput.Handle    := context;        // je treba uchovat kontext, jinak nebude mozne vratit hodnotu
  5.   Func.DoFinalize(Self);
  6. end;
V dictionary v ramci Finalize som vyhladaval pomocou HandleOld
To funguje aj v pripade pouzitia Group By

Jo takhle to myslis. No a mas garanci ze se nebude volat v poradi:

Kód: Delphi [Vybrat]
  1. OnCalculate - MojTotal(pole1)
  2. OnCalculate - MojTotal(pole2)
  3. OnFinalize - MojTotal(pole1)

Nejspis by nemelo, ale kdyby ano, zalohoval bys jiny kontext. Sel bych radeji cestou k tomu urcenou.
96
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Miroslav Baláž kdy 06-04-2018, 15:29:09 »
Ukazka by sa urcite hodila.
Ja som pre vyhladanie v dictionary (ta sa naplna pri krokovom prechadzani) vyuzil tuto konstrukciu:
Kód: Delphi [Vybrat]
  1. procedure TSQLiteFunctionInstance.DoFinalize(context: psqlite3_context);
  2. begin
  3.   FOutput.HandleOld := FOutput.Handle; // Miro doplnene HandleOld  6.4.2017
  4.   FOutput.Handle    := context;        // je treba uchovat kontext, jinak nebude mozne vratit hodnotu
  5.   Func.DoFinalize(Self);
  6. end;
Pred tymto priradenim: "FOutput.Handle    := context;" handle obsahuje ten povodny "krokovy" handle
V dictionary v ramci Finalize potom vyhladavam pomocou HandleOld
To funguje aj v pripade pouzitia Group By
97
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Delfin kdy 06-04-2018, 15:22:26 »
Lenže nové Output.Handle už neumožní vyhľadanie hodnoty v Dictionary, pretože sa zmeni riešením pre Aggregate.
Musel som použiť ešte ďalšiu property FHandleOld, pre zachovanie FHandle. Potom to už funguje.

Ten navrzeny fix je spravne. Ne pro Tebe, protoze se snazis rozlisit jednotliva volani funkci v ramci SQL prikazu. To FireDAC nema.

Pokud pocitas v OnCalculate v Dictionary<AOutput.Handle, Value>, pak zapominas na to, ze ten finalizacni kontext dopredu neznas, stejne jako on nezna kontext krokovy. Jakym zpusobem chces priradit pri finalizaci vysledek? Kterou polozku z dictionary s vysledky pro dane volani vyberes?

Reseni samozrejme existuje. SQLite pro tento pripad pouziva sqlite3_aggregate_context. Funguje tak, ze pri prvnim volani v krokovem callbacku sqlite3_aggregate_context engine alokuje blok pameti a vrati Ti na nej ukazatel. S kazdym dalsim volanim krokoveho callbacku vrati stejny ukazatel. Ve finalizacnim callbacku pak (tentokrat s jinym kontextovym handle nez mel k dispozici krokovy callback) vrati ten stejny pointer ktery Ti vratil SQLite v callbacku krokovem. To je zpusob jakym provazat krokovy a finalizacni callback.

Jestli chces, muzu Ti poslat ukazku.
98
Ostatní DB / Re:SQLite: TFDSQLiteFunction využitie parametra Aggregated
« Poslední příspěvek od Miroslav Baláž kdy 06-04-2018, 15:06:20 »
Trochu problém, toto riešenie funguje len pre jednu inštanciu funkcie v rámci SQL.
Viacnásobné požitie tej iste funkcie v SQL vyššie uvedeným spôsobom nefunguje  :
Kód: MySQL [Vybrat]
  1. SELECT MojTotal(pole1), MojTotal(pole2) FROM xy
Pre funkcie, ktoré nie sú aggregate, by sa dalo využiť tvoje: AOutput.Handle + Dictionary.
Jednoduchým skombinovaním dvoch riešení to nejde.
Link na tvoj príspevok, kde navrhuješ postup pre viac inštancií jednej funkcie:
Lenže nové Output.Handle už neumožní vyhľadanie hodnoty v Dictionary, pretože sa zmeni riešením pre Aggregate.
Bijú sa tieto dva čiastkové kódy:
Kód: Delphi [Vybrat]
  1. if not FResults.TryGetValue(AOutput.Handle, Value) then
  2.     Value := AInputs[0].AsInteger
  3.   else
  4.     Value := Value + AInputs[0].AsInteger;
  5.   FResults.AddOrSetValue(AOutput.Handle, Value);
V rámci opravy Finalize, sa priradí iný handle, než je v Dictionary:
Kód: Delphi [Vybrat]
  1. procedure TSQLiteFunctionInstance.DoFinalize(context: psqlite3_context);
  2. begin
  3.   FOutput.Handle := context; // je treba uchovat kontext, jinak nebude mozne vratit hodnotu
  4.   Func.DoFinalize(Self);
  5. end;
[/quote]
Musel som použiť ešte ďalšiu property FHandleOld, pre zachovanie FHandle. Potom to už funguje.
99
Obecné / Re:Násobenie čísla, nie výrazu, jednotkou.
« Poslední příspěvek od Radek Červinka kdy 06-04-2018, 14:34:03 »
vandrovnik: no a kdyz uz jsi v tom, tak jsi to mohl zkusit i v realnych číslech proti 64bit kompilatoru a s
Kód: [Vybrat]
{$EXCESSPRECISION ON} nebo {$EXCESSPRECISION OFF}

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Floating_point_precision_control_%28Delphi_for_x64%29
100
Obecné / Re:Násobenie čísla, nie výrazu, jednotkou.
« Poslední příspěvek od vandrovnik kdy 06-04-2018, 14:25:28 »
Jinak nějakou optimalizaci si dělá i procesor, takže bych to v kódu pro 20 tisíc položek rozhodně neřešil.
Násobení jedničkou mu jde rychleji než násobení nějakým ošklivým číslem.

U mě to vyšlo zhruba 35578919 tiků pro násobení jedničkou a 35653693 tiků pro násobení tím ošklivým číslem.


Kód: [Vybrat]
var a:integer;
     t:tStopWatch;
     x,y,z:UInt64;
 begin
 t:=t.Create;
 x:=$cfcfcfcfcfcfcfcf;
 y:=1;
 t.Start;
 for a:=1 to $7FFFFFFF do z:=x*y;
 t.Stop;
 v1.Caption:=IntToStr(t.ElapsedTicks);
 //
 x:=$cfcfcfcfcfcfcfcf;
 y:=$fcfcfcfcfcfcfcfc;
 t.Reset;
 t.Start;
 for a:=1 to $7FFFFFFF do z:=x*y;
 t.Stop;
 v2.Caption:=IntToStr(t.ElapsedTicks);

Stran: 1 ... 8 9 [10]