Rust - std::ANY alebo lepší návrh?

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #15 kdy: 17. 11. 2021, 16:17:18 »
Devirtualizovat to asi vždy půjde jen omezeně
To dá rozum, když je to heuristická optimalizace. Typicky se používá v různých JIT překladačích a runtimech à la Smalltalk. Rust prostě tuhle optimalizaci (zatim?) nemá, pro C++ existuje údajně v experimentální formě. Každopádně až v Rustu bude, enumy už nebudou mít výhodu rychlosti.


Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #16 kdy: 17. 11. 2021, 16:28:27 »

Debilní root fórum systém, psal jsem se s tím asi půl hodiny, mezitím mě to odhlásilo a příspěvek nenávratně zmizel. Tak ještě jednou v rychlosti:

push<T: DatabaseBuilder> - dobrý.

Chtělo by to trochu učesat:

Nelíbí se mi ty Optiony v push, create_table, a možná i v Database, myslím že by bylo lepší je zrušit. Navíc bych čekal, že budou brát &mut self.

Kdyby ses chtěl zbavit těch DatabaseMembers, který jsou opravdu podivný, mohla by se třeba udělat lazy inicializace tabulek přímo v Database, např. něco jako (nevím jestli půjde přeložit)

pub struct Database {
    initialized_tables: HashSet<TypeId>,
    c: Connection,
}

impl Database {
    fn init_table<T: DatabaseBuilder + 'static>(&mut self) {
        let type_id = TypeId::of::<T>();
        if !self.initialized_tables.contains(&type_id) {
            T::create_table(&self.c);
            self.initialized_tables.insert(type_id);
        }
    }

    pub fn push<T: DatabaseBuilder + 'static>(&mut self, data: &T) {
        self.init_table::<T>();
        data.push(&self.conn)
    }
}

Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #17 kdy: 17. 11. 2021, 16:33:27 »
Devirtualizovat to asi vždy půjde jen omezeně
To dá rozum, když je to heuristická optimalizace. ...Každopádně až v Rustu bude, enumy už nebudou mít výhodu rychlosti.

Spíš bych řekl, že "až v Rustu bude, enumy v některých případech už nebudou mít výhodu rychlosti, nebo bude rozdíl v rychlosti menší".

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #18 kdy: 17. 11. 2021, 17:42:06 »

Debilní root fórum systém, psal jsem se s tím asi půl hodiny, mezitím mě to odhlásilo a příspěvek nenávratně zmizel. Tak ještě jednou v rychlosti:

push<T: DatabaseBuilder> - dobrý.

Chtělo by to trochu učesat:

Nelíbí se mi ty Optiony v push, create_table, a možná i v Database, myslím že by bylo lepší je zrušit. Navíc bych čekal, že budou brát &mut self.

Kdyby ses chtěl zbavit těch DatabaseMembers, který jsou opravdu podivný, mohla by se třeba udělat lazy inicializace tabulek přímo v Database, např. něco jako (nevím jestli půjde přeložit)

pub struct Database {
    initialized_tables: HashSet<TypeId>,
    c: Connection,
}

impl Database {
    fn init_table<T: DatabaseBuilder + 'static>(&mut self) {
        let type_id = TypeId::of::<T>();
        if !self.initialized_tables.contains(&type_id) {
            T::create_table(&self.c);
            self.initialized_tables.insert(type_id);
        }
    }

    pub fn push<T: DatabaseBuilder + 'static>(&mut self, data: &T) {
        self.init_table::<T>();
        data.push(&self.conn)
    }
}
Zrovna TypeId je stejně haram jako Any.

Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #19 kdy: 17. 11. 2021, 21:40:24 »
Dik za hint, mas pravdu, to s tym Option optimalizujem (:
K tomu navrhu cez Lazy Init, super napad, rovno to pouzijem, uvazoval som ale nic lepsie ma prakticky na momentalne sksuenosti nenapada.

Este raz dik za hint.


Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #20 kdy: 17. 11. 2021, 22:04:59 »
K tomu navrhu cez Lazy Init, super napad, rovno to pouzijem, uvazoval som ale nic lepsie ma prakticky na momentalne sksuenosti nenapada.
Jde to elegantněji přes get_or_insert.

Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #21 kdy: 17. 11. 2021, 22:16:35 »
K tomu navrhu cez Lazy Init, super napad, rovno to pouzijem, uvazoval som ale nic lepsie ma prakticky na momentalne sksuenosti nenapada.
Jde to elegantněji přes get_or_insert.

Diky za hint, vyzera to ako tiez dobra cesta :)

Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #22 kdy: 18. 11. 2021, 09:14:09 »
Zrovna TypeId je stejně haram jako Any.

Jo, já osobně TypeId taky zatím nikdy nepoužil, ale pro tohle zadání mi to přišlo jako elegantní jednoduchý řešení .. alespoň jsem nepřišel na lepší, napadá tě něco?

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #23 kdy: 18. 11. 2021, 09:33:52 »
Zrovna TypeId je stejně haram jako Any.
Jo, já osobně TypeId taky zatím nikdy nepoužil, ale pro tohle zadání mi to přišlo jako elegantní jednoduchý řešení .. alespoň jsem nepřišel na lepší, napadá tě něco?
Ne, ale je to stejně nesystémové jako Any. Jasně se ukazuje, že Rust potřebuje aspoň nějaký malý stabilní runtime, pokud chce věrohodně rozšířit pole působnosti. I když s C++ si nemá co vyčítat. (Podle interních informací z Googlu je právě tohle důvodem, proč Rust více nepodporují na App Engine a jiných cloudových službách.)

Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #24 kdy: 18. 11. 2021, 09:38:16 »
K tomu navrhu cez Lazy Init, super napad, rovno to pouzijem, uvazoval som ale nic lepsie ma prakticky na momentalne sksuenosti nenapada.
Jde to elegantněji přes get_or_insert.

HashSet::get_or_insert je nightly, a stejně nevím jak by se to na to dalo použít. Šlo by použít get_or_insert_with, a tu closure na počítání hodnoty k vložení do HashSety zneužít k inicializaci tabulky takhle: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d221825d869185554b7077d109a55157 , ale jestli je to elegantnější, to je s otazníkem. Je fakt, že to možná bude o trochu rychlejší, odpadne duplicitní lookup, ale možná že by to optimalizátor v té první verzi eliminoval.

Kdybych nechtěl používat nightly a chtěl to takhle v jednom kroku, dala by se místo HashSet použít HashMap<TypeId, ()> a entry api HashMap-y, za cenu jistého zamlžení sémantiky (premature optimization is the root of all evil, že).

K tomu pro zajímavost - přesně takhle je v rustu implementovaná HashSet - když to zjednoduším, je to obal nad HashMapou s unit hodnotama, mírně zjednodušeno

pub struct HashSet<T> {
    map: HashMap<T, ()>,
}

impl<T> HashSet<T> {
    pub fn contains<Q>(&self, value: &Q) -> bool
    {
        self.map.contains_key(value)
    }

 // atp...
}

Přijde mi naprosto úžasný, že takhle definovaná HashSeta je optimálně rychlá, nemusí se znovu nic reimplementovat, unit hodnoty vnitřní hashmapy se vyoptimalizují pryč.




Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #25 kdy: 18. 11. 2021, 09:40:49 »
Zrovna TypeId je stejně haram jako Any.
Jo, já osobně TypeId taky zatím nikdy nepoužil, ale pro tohle zadání mi to přišlo jako elegantní jednoduchý řešení .. alespoň jsem nepřišel na lepší, napadá tě něco?
Ne, ale je to stejně nesystémové jako Any. Jasně se ukazuje, že Rust potřebuje aspoň nějaký malý stabilní runtime, pokud chce věrohodně rozšířit pole působnosti. I když s C++ si nemá co vyčítat. (Podle interních informací z Googlu je právě tohle důvodem, proč Rust více nepodporují na App Engine a jiných cloudových službách.)

Můžeš rozvést, co myslíš v tomhle případě runtimem, a k čemu by měl být Rustu užitečný?

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #26 kdy: 18. 11. 2021, 10:32:47 »
odpadne duplicitní lookup
Ano, a na tohle by se mělo hledět vždy. (Zvlášť lidi od C++ tohle hned v kódu vidí a kritizují :) neb STL tohle řeší hezky.)

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #27 kdy: 18. 11. 2021, 10:34:37 »
K tomu pro zajímavost - přesně takhle je v rustu implementovaná HashSet - když to zjednoduším, je to obal nad HashMapou [...] Přijde mi naprosto úžasný, že takhle definovaná HashSeta je optimálně rychlá, nemusí se znovu nic reimplementovat, unit hodnoty vnitřní hashmapy se vyoptimalizují pryč.
Jo, to je známý pattern, Go to má stejně tak (ani nic nemusí optimalizovat, má struct{}).

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #28 kdy: 18. 11. 2021, 10:46:07 »
Můžeš rozvést, co myslíš v tomhle případě runtimem, a k čemu by měl být Rustu užitečný?
Myslím to, to myslí runtimem autoři Rustu (chlubíce se, že žádný nemá). Nechci zabředávat do diskusí (osobně mě absence runtimu, autory tolik vychvalovaná, netrápí, máme přece C++, Javu, Go, .NET Core :) etc., každý dle svého gusta), ale právě lidi od App Engine si stěžují na absenci alespoň elementární dynamické reflexe (statická se dá v Rustu nasimulovat a hodně modulů to dělá). Proto zatím App Engine nemá plnou podporu pro Rust, těžko se jim integruje s jejich Datastorem, Memcache apod. IMHO tohle už není pole působnosti Rustu, ale někteří rustí nadšenci by ho zřejmě chtěli vidět všude a Google neustále "otravují" :) Podle jednoho jejich vývojáře chtějí přidat C++, až bude mít odsouhlasené některé TS (přesunuté do C++23), to se pak rustíci pominou, že je C++ předběhlo :D

Dle mého subjektivního názoru je možná i lepší, že tam ten dynamický runtime není, začátečníci jsou tak nuceni psát pořádně objektově (resp. traitově, kdyby někdo trval na implikaci OO=>dědičnost). Problém ale je v případech, kdy by se hodil, a těžko může být jedna verze Rustu pro juniory a jiná pro ty, kteří ví, co dělají, a dynamičnost nezneužijí k přiohnutí jazyka či návrhu.

Re:Rust - std::ANY alebo lepší návrh?
« Odpověď #29 kdy: 18. 11. 2021, 11:42:32 »
odpadne duplicitní lookup
Ano, a na tohle by se mělo hledět vždy. (Zvlášť lidi od C++ tohle hned v kódu vidí a kritizují :) neb STL tohle řeší hezky.)

Koukám že HashSet::insert vrací, jestli už tam vkládaný prvek byl nebo ne, takže se to celý dá zjednodušit na optimální

    fn init_table<T: DatabaseBuilder + 'static>(&mut self) {
        let type_id = TypeId::of::<T>();
        if self.initialized_tables.insert(type_id) {
            T::create_table(&mut self.c);
        }
    }

Jak by se to dělalo se Set-ou v C++ STL?