Autor Téma: Benchmark: Dictionary vs StringList vs HashedStringList vs SQLite in Memory  (Přečteno 1476 krát)

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Prehľadávanie zoznamu (text), za rovnakých podmienok. Nástroje zoradené podľa dosiahnutého výsledku :
Kód: HTML [Vybrat]
  1. TDictionary
  2. THashedStringList(je deklarovaný v IniFiles)
  3. SQLite (inMemory)
  4. TStringList
Výsledky sú dramaticky rozdielne. Podrobnosti v priloženom obrázku.
TDictionary všetkých jasne valcuje.
Oba StringList-y boli sorted a vyhľadávalo sa cez IndexOf, čo ešte neznamená, že už máme aj hodnotu TRecord z pointera
Zaujímavé, že HashedStringList bol takmer 100x rýchlejší ako StringList
SQLite (InMemory), sa drží voči StringListu veľmi dobre, ale inak za prvými dvoma zaostáva veru hodne.
SQLite vyhľadávanie :
Kód: MySQL [Vybrat]
  1. SELECT eCategSet, eFnFlagSet FROM sumar WHERE wordItem=?
SQLiteStatement bol Prepared
Kód: MySQL [Vybrat]
  1. CREATE TABLE if not exists [sumar] ( wordItem varchar( 64 ) PRIMARY KEY NOT NULL COLLATE BINARY, eCategSet INT64, eFnFlagSet INTEGER
Nepoužil som Komponenty FireDAC. Napríklad FDMemTable.
Možno má zabudované nejaké optimalizácie. Ale je len málo pravdepodobné, že by porazila v rýchlosti TDictionary
« Poslední změna: 16-12-2017, 19:15:16 od mibainfo »

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Íííha:
Rozdiel medzi týmto (PRIMARY KEY):
Kód: MySQL [Vybrat]
  1. CREATE TABLE [sumar] ( wordItem varchar( 64 ) PRIMARY KEY NOT NULL COLLATE BINARY, eCategSet INT64, eFnFlagSet INTEGER
Nepoužil som Komponenty FireDAC. Napríklad FDMemTable.
Možno má zabudované nejaké optimalizácie. Ale je len málo pravdepodobné, že by porazila v rýchlosti TDictionary
a týmto (Bez Indexu)
Kód: MySQL [Vybrat]
  1. CREATE TABLE [sumar] ( wordItem varchar( 64 ) NOT NULL COLLATE BINARY, eCategSet INT64, eFnFlagSet INTEGER
je 10 násobok.
Prvé 406 milisekúnd, druhé 4773.
Teda s Primary key je výsledok viac ako 10-krát rýchlejší.

Toto je prakticky rovnako rýchle ako PRIMARY KEY ( wordItem ako UNIQUE a UNIQUE INDEX )
Kód: MySQL [Vybrat]
  1. CREATE TABLE [sumar] ( wordItem varchar( 64 ) UNIQUE ON CONFLICT ABORT NOT NULL, eCategSet INT64, eFnFlagSet INTEGER );
  2. CREATE UNIQUE INDEX sumarIdx ON [sumar] (wordItem ASC)

Dokonca aj bez indexu, stačilo iba pole definované ako UNIQUE a trvanie je len 396 milissekúnd:
Kód: MySQL [Vybrat]
  1. CREATE TABLE if not exists [sumar] ( wordItem varchar( 64 ) UNIQUE NOT NULL, eCategSet INT64, eFnFlagSet INTEGER );
Podotýkam, že databáza je InMemory a po každom spustení sa začína bez tabuliek

Prikladám doplnenú tabuľku.
« Poslední změna: 16-12-2017, 21:52:00 od mibainfo »

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 742
  • Karma: 32
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Zajimave. Jen se v tom nejak nedokazu zorientovat. Kolik tedy bylo polozek v kolekcich a jak dlouhy klic? Mohli bychom ziskat ke stazeni testovaci aplikaci?
I'm a soldier, so don't panic!

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Pre zaujímavosť prikladám aj test pre FIREBIRD 3.0 EMBEDED
Čas bol poslabší cca 29 000 milisekúnd.
Kód: MySQL [Vybrat]
  1. CREATE TABLE sumar ( wordItem varchar( 64 ) NOT NULL primary key, eCategSet BIGINT, eFnFlagSet INTEGER );
Kód som nevedel lepšie než takto:
Kód: Delphi [Vybrat]
  1.   stw.Reset;
  2.   stw.Start;
  3.   dm.qry.Params.Clear;
  4.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
  5.   dm.qry.Params[ 0 ].DataType := ftString;
  6.   dm.qry.Params[ 0 ].Size := 64;
  7.   dm.qry.Params[ 0 ].IsCaseSensitive := false;
  8.   dm.qry.Prepare;
  9.   k := 0;
  10.   with dm.qry do
  11.     for i := 1 to 50000 do
  12.       begin
  13.       Params[ 0 ].AsString := 'oxymoron';
  14.       Active := true;
  15.       if not eof then
  16.         Inc( k );
  17.       Active := False;
  18. ..  // Dalsie slova. Natvrdo nakodovane, tak ako ten oxymoron. Zoznam je nizsie
  19.       end;
  20.  
  21.   stw.Stop;
  22.   imilisec := stw.ElapsedMilliseconds;     // 28900
Hľadalo sa v cykle týchto 7 slov :
'oxymoron','query','abcd','#endwhile','date','vba_bitwise','current_timestamp'
Cyklus bol:
For i = 1  to 50 000
Dictionary/resp. Tabulka, obsahuje celkom 221 slov.

Offline Delfin

  • Guru
  • *****
  • Příspěvků: 742
  • Karma: 32
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Pre zaujímavosť prikladám aj test pre FIREBIRD 3.0 EMBEDED
Čas bol poslabší cca 29 000 milisekúnd.
Kód: MySQL [Vybrat]
  1. CREATE TABLE sumar ( wordItem varchar( 64 ) NOT NULL primary key, eCategSet BIGINT, eFnFlagSet INTEGER );
Kód som nevedel lepšie než takto:
Kód: Delphi [Vybrat]
  1.   stw.Reset;
  2.   stw.Start;
  3.   dm.qry.Params.Clear;
  4.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
  5.   dm.qry.Params[ 0 ].DataType := ftString;
  6.   dm.qry.Params[ 0 ].Size := 64;
  7.   dm.qry.Params[ 0 ].IsCaseSensitive := false;
  8.   dm.qry.Prepare;
  9.   k := 0;
  10.   with dm.qry do
  11.     for i := 1 to 50000 do
  12.       begin
  13.       Params[ 0 ].AsString := 'oxymoron';
  14.       Active := true;
  15.       if not eof then
  16.         Inc( k );
  17.       Active := False;
  18. ..  // Dalsie slova. Natvrdo nakodovane, tak ako ten oxymoron. Zoznam je nizsie
  19.       end;
  20.  
  21.   stw.Stop;
  22.   imilisec := stw.ElapsedMilliseconds;     // 28900
Hľadalo sa v cykle týchto 7 slov :
'oxymoron','query','abcd','#endwhile','date','vba_bitwise','current_timestamp'
Cyklus bol:
For i = 1  to 50 000
Dictionary/resp. Tabulka, obsahuje celkom 221 slov.

Ty mu ublizujes :) Dataset otevri a men jen parametr a volej Refresh. Ale zpet k tomu benchmarku - prijemne me prekvapilo ze je hashovani rychlejsi nez hledani pulenym intervalem s tak malym poctem polozek.

Jinak samozrejme hledani indexovaneho sloupce bude rychlejsi nez bez nej. K tomu index existuje. Ale hledani bude pomalejsi nez nativni kolekce (index bude totiz zase jen hash kolekce). Pujde tam o overhead v podobe volani klientske knihovny - tady neverim ze by nekdo v DBMS dokazal implemetovat mnohem rychlejsi hash kolekci nez ma Delphi.

P.S. stopky se daji vytvorit jednou metodou, StartNew.
« Poslední změna: 17-12-2017, 01:01:29 od Delfin »
I'm a soldier, so don't panic!

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Delfin dík  :)
Tvoj návrh výrazne pomohol: čas sa skrátil na tretinu pôvodného: 9 713 ms  vs 29 700
Kód: Delphi [Vybrat]
  1.   stw.Reset;
  2.   stw.Start;
  3.   dm.qry.Params.Clear;
  4.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
  5.   dm.qry.Params[ 0 ].DataType := ftString;
  6.   dm.qry.Params[ 0 ].Size := 64;
  7.   dm.qry.Params[ 0 ].IsCaseSensitive := false;
  8.   dm.qry.Prepare;
  9.   dm.qry.Active := true;
  10.   k      := 0;
  11.   with dm.qry do
  12.     for i := 1 to 50000 do
  13.       begin
  14.       Params[ 0 ].AsString := 'oxymoron';
  15.       Refresh;
  16.       if not eof then
  17.         Inc( k );
  18.       Params[ 0 ].AsString := 'query';
  19.       Refresh;
  20. ..
  21.       Params[ 0 ].AsString := 'current_timestamp';
  22.       Refresh;
  23.       if not eof then
  24.         Inc( k );
  25.       end;
  26.   dm.qry.Active := False;
  27. stw.Stop;
  28. iMilisec := stw.ElapsedMilliseconds;     // 9 713 vs 28900
  29.  

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
Jinak samozrejme bude hledani indexovaneho sloupce rychlejsi nez bez nej. K tomu index existuje. Ale hledani bude pomalejsi nez nativni kolekce (index bude totiz zase jen hash kolekce).
No namatkou som robil pokusy aj s indexami:
  • Keď už som pri FB, tak najprv toto: PRIMARY KEY a UNIQUE sa vzájomne vylučujú. Čas sa líši medzi nimi len minimálne
  • Podobný efekt, že PRIMARY KEY a UNIQUE, sú výkonovo takmer identické, bol aj u SQLite
  • U SQLite: ak som dal len index a ten nebol ani UNIQUE ani PRIMARY KEY, tak jeho efekt bol veľmi slabý
  • Stojí za povšimnutie, že pracujem s ASCII 128 a case sensitive


Offline Delfin

  • Guru
  • *****
  • Příspěvků: 742
  • Karma: 32
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Jinak samozrejme bude hledani indexovaneho sloupce rychlejsi nez bez nej. K tomu index existuje. Ale hledani bude pomalejsi nez nativni kolekce (index bude totiz zase jen hash kolekce).
No namatkou som robil pokusy aj s indexami:
  • Keď už som pri FB, tak najprv toto: PRIMARY KEY a UNIQUE sa vzájomne vylučujú. Čas sa líši medzi nimi len minimálne
  • Podobný efekt, že PRIMARY KEY a UNIQUE, sú výkonovo takmer identické, bol aj u SQLite
  • U SQLite: ak som dal len index a ten nebol ani UNIQUE ani PRIMARY KEY, tak jeho efekt bol veľmi slabý
  • Stojí za povšimnutie, že pracujem s ASCII 128 a case sensitive

Tady bych nez pokusy zvazil si o tematech neco precist ;)

- je jedno jaky DBMS; primarni klic je unikatni identifikator, proto je pro SQL nesmysl si vyptavat unikatnost podruhe
- protoze jsou oba indexy vnitrne hash kolekcemi
- protoze nema hash kolekci (teoreticky by mohl, s ukazateli na skupinu zaznamu)
- tomu nerozumim ::) :) (ale napr. muj oblibeny DBMS umoznuje vytvorit i "case insensitive" index - ale i fulltext search a dalsi)
« Poslední změna: 17-12-2017, 01:49:04 od Delfin »
I'm a soldier, so don't panic!

Offline Miroslav Baláž

  • Plnoletý
  • ***
  • Příspěvků: 197
  • Karma: 5
    • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
    • Stojí za povšimnutie, že pracujem s ASCII 128 a case sensitive

    - tomu nerozumim ::) :)
    Pracujem so slovami, ktoré môžu obsahovať iba znaky #32 až max 'z' a z toho je výnimka oblasť 'A'..'Z'.
    Tak napríklad StringList má v tomto prípade smolu, že je case Insenzitive
    A naopak HashedStringList je zrejme tiež case insensitive a pritom dosahuje skvelý čas.

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    Pracujem so slovami, ktoré môžu obsahovať iba znaky #32 až max 'z' a z toho je výnimka oblasť 'A'..'Z'.
    Tak napríklad StringList má v tomto prípade smolu, že je case Insenzitive
    A naopak HashedStringList je zrejme tiež case insensitive a pritom dosahuje skvelý čas.

    Case insensitive hash list si muzes vytvorit jednoduse tak, ze vsechna slova prevedes na upper nebo lower case a pri hashovani klice udelas to same. Zadna slozitost. A string list nema az tak smulu, mozna jsi k nemu jen "nefer". Proto jsem chtel videt testovaci aplikaci ;)

    Bohuzel ani ted netusim kolik polozek je v kolekcich ani jak dlouhy je klic. To jsou podstatne informace pro benchmark.
    « Poslední změna: 17-12-2017, 02:14:25 od Delfin »
    I'm a soldier, so don't panic!

    Offline Miroslav Baláž

    • Plnoletý
    • ***
    • Příspěvků: 197
    • Karma: 5
      • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
    V tomto príspevku, keď sa naňho riadne pozrieš, je komplet info.
    Pre zaujímavosť prikladám aj test pre FIREBIRD 3.0 EMBEDED
    Čas bol poslabší cca 29 000 milisekúnd.
    Kód: MySQL [Vybrat]
    1. CREATE TABLE sumar ( wordItem varchar( 64 ) NOT NULL primary key, eCategSet BIGINT, eFnFlagSet INTEGER );
    Kód som nevedel lepšie než takto:
    Kód: Delphi [Vybrat]
    1.   stw.Reset;
    2.   stw.Start;
    3.   dm.qry.Params.Clear;
    4.   dm.qry.SQL.Text := 'select eCategSet, eFnFlagSet from sumar where wordItem = ?';
    5.   dm.qry.Params[ 0 ].DataType := ftString;
    6.   dm.qry.Params[ 0 ].Size := 64;
    7.   dm.qry.Params[ 0 ].IsCaseSensitive := false;
    8.   dm.qry.Prepare;
    9.   k := 0;
    10.   with dm.qry do
    11.     for i := 1 to 50000 do
    12.       begin
    13.       Params[ 0 ].AsString := 'oxymoron';
    14.       Active := true;
    15.       if not eof then
    16.         Inc( k );
    17.       Active := False;
    18. ..  // Dalsie slova. Natvrdo nakodovane, tak ako ten oxymoron. Zoznam je nizsie
    19.       end;
    20.  
    21.   stw.Stop;
    22.   imilisec := stw.ElapsedMilliseconds;     // 28900
    Hľadalo sa v cykle týchto 7 slov :
    'oxymoron','query','abcd','#endwhile','date','vba_bitwise','current_timestamp'
    Cyklus bol:
    For i = 1  to 50 000
    Dictionary/resp. Tabulka, obsahuje celkom 221 slov.
    Mam sice testovaci program, ale je to kopia mojho hlavneho programu (90%) a Benchmark je zbytok.
    Zatiaľ je taký stav, že vyňatie všetkých testov by mi trvalo veľmi dlho.

    Offline Miroslav Baláž

    • Plnoletý
    • ***
    • Příspěvků: 197
    • Karma: 5
      • Verze Delphi: D1,2,3,4,7,2005,2009, XE8,S,B,T10.2.2 Pro
    Doplnená tabuľka výsledkov
    Možno prihodím ešte Access cez ActiveX ADO.
    Tak nejako tuším, že nebude na tom zrovna zle.
    Inak Access cez ODBC, čo teraz presadzuje Microsft je hrôza.
    20 rokov som používal ADO. Nech sa spamätajú a nech nemenia, čo je dobré
    « Poslední změna: 17-12-2017, 02:57:07 od mibainfo »

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    V tomto príspevku, keď sa naňho riadne pozrieš, je komplet info.

    Zkousel jsem ale neni. Muzu z nej vycist ze pouzivas 64 znakovy ANSI string jako klic (coz muze byt nefer vzhledem k Unicode hashovani v Delphi) a vzorek 50k opakovani. Delka klicu je neznama - vime o klici "oxymoron" (8 znaku). Kolik zaznamu je v kolekci (nebo tabulce) se zjistit neda.
    « Poslední změna: 17-12-2017, 03:03:28 od Delfin »
    I'm a soldier, so don't panic!

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    Doplnená tabuľka výsledkov
    Možno prihodím ešte Access cez ActiveX ADO.
    Tak nejako tuším, že nebude na tom zrovna zle.
    Inak Access cez ODBC, čo teraz presadzuje Microsft je hrôza.
    20 rokov som používal ADO. Nech sa spamätajú a nech nemenia, čo je dobré

    Vzpamatuji? ADO je postavene na OLE DB jehoz naslednikem je ODBC. Vzhledem k poctu implementaci by IMHO ani pres snahu Microsoftu OLE DB vzkrisit melo radeji v 21. stoleti ze sveta odejit. Microsoft ve svych OS podporuje stare API s tim ze nabizi i nove alternativy, coz je super (spousta novych vznikla - a nektere jsou opravdu zajimave a Delphi je [zatim] neimplementuje). Tohle je odvetvi ktere sleduju s kazdym novym SDK (resim totiz konzultace vicemene vyhradne pro Windows; MSVC a Delphi co se tyce jazyku).
    « Poslední změna: 17-12-2017, 03:21:53 od Delfin »
    I'm a soldier, so don't panic!

    Offline Delfin

    • Guru
    • *****
    • Příspěvků: 742
    • Karma: 32
    • SW konzultant
      • Verze Delphi: 2009, Tokyo
    20 rokov som používal ADO. Nech sa spamätajú a nech nemenia, čo je dobré

    Navic ta veta je bohuzel dost nostalgicka (ale to mi prijde tak nejak cele toto forum; prosim jen neberte tento muj nazor osobne :) - jde o nazory, v zadnem pripade ne o vek!). Prijde mi to jako rict, 20 roku jezdim Favoritem, vyrabejte ho dal. U programovani je nostalgie o to horsi (byt se i ten Favorit da "udrzet na ceste"). Vidim to i u mnoha klientu kteri se me snazi presvedcit ze se jejich mnoha-set-formova aplikace neda zjednodusit. Da, a kolikrat se pak biji do hlavy ze se na ne programator vykaslal a oni mu za ty hodiny psani opakovaneho kodu tolik zaplatili. Na to jim odpovidam, navrhove sablony vznikly velice davno a slo jen o nezkusenost programatora - a nelzu, ty zakladni existuji velmi dlouho, jen je treba se kolikrat pred psanim kodu zamyslet nad tim co muze byt spolecne. Vic kodu neni vic Adidas :)

    Z praxe, jako prvni u klientu kteri chteji rozsahle upravy jednodussi Delphi aplikaci radim "jste schopni ji prevest do jineho jazyka"? Nebo ty co me kontaktuji s tim ze je jejich >30GB (nejmenovana) databaze "pomala" ocastuju po profilovani dotazem, "jste schopni prejit na jiny DBMS"? A spousta dalsich veci. Chystam Delphi blog se spoustou informaci z praxe, nejen ceskeho programovani (kvuli casu a dostupnosti asi jen v anglictine). Pak kdyztak muzu poslat odkaz...
    « Poslední změna: 17-12-2017, 04:34:50 od Delfin »
    I'm a soldier, so don't panic!

     

    S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

    Upozornění: do tohoto tématu bylo naposledy přispěno před 120 dny.
    Zvažte prosím založení nového tématu.

    Jméno: E-mail:
    Ověření:
    Křestní jméno zpěváka Gotta: