No, mám tady na stole jednu desku. Procesor honím na 168MHz (vychází tak nejlíp časování periferek, dal by o něco víc). Má to 4x64 kiB RAM + 2x 1MB FLAH.
Mám tam ovladače pro Ethernet dělat v Javě? VM tam nedostanu ani omylem, nevím co Java přibalí z knihoven a jestli toho nebude v té binárce 0,5GB - pokud jo, nic s tím neudělám. Zaintegrovat HW pro HASH a HW crypto engine by byla ještě o level větší sranda... A nesmí to kleknout kvůli fragmentaci paměti.
Článek je o tom, že je Java použitelná i na low level věci. Tak se ptám, jestli by Java dala i takovouhle věc.
Ono totiž
- C blbě pracuje s objektama (socket atd. se jako třída přímo nabízí, takže to smrdí OOP)
- C++ má náročnou správu paměti
- Go - zatím jsem nezkoumal možnosti
- Java - viz komentáž výše. Nevím, co všechno se tam pokusí narvat
Napadá někoho jiný řešení?
Z hlediska programátora - musí se rozmyslet, kde objekt založí - heap nebo stack, kdo bude vlastníkem, kdy je případně třeba vlastnictví předat, nově do toho přichází unique/shared. To vše ovlivňuje jak se bude objekt předávat dál (hodnota, reference, pointer, ...), jak bude algoritmus navržen atd. U složitějších algoritmů to v podstatě vede na to, že programátor píše vlastní obdobu GC zas a znovu.
Z hlediska runtime - je zde mnohem složitější logika jak při alokaci tak dealokaci, výkonnostní dopady v případě sdílených pointerů, nevyhnutelné problémy jako např. defragmentace. To následně dále vyvolává tlak na programátora, aby tomu ještě víc přizpůsoboval design programu, musel optimalizovat apod.
Ve výsledku je programátor nucen zabývat se těmito aspekty v C++ násobně déle než kolik na to je potřeba třeba v javě (ale vlastně v čemkoli co má rozumný GC).
Jedinou výhodu kterou za to dostaneme jsou nižší paměťové nároky a někdy se může hodit deterministická dealokace. Samozřejmě existují případy, kdy je lepší to psát v C++ (programátor je dostupnější než RAM), ale většinou jsou výše uvedená negativa příliš.
No a nie je to skôr tak, že sa človek primárne rozhoduje o iných veciach, ako napríklad či chce mať prístup k danému prostriedku zdieľaný, alebo či je jeho vlastníctvo exkluzívne, alebo či potrebuje presne vedieť kedy skončí životnosť objektu, alebo podobné záležitosti a na základe toho potom vyplynie typ objektu, miesto jeho existencie a signatúra funkcie? Ja si myslím, že je :-) No a ak má chaos v tom ako to vlastne má byť, tak je jasné, že to bude prepisovať. Ale je to chyba C++? To ani náhodou.
C++ dáva možnosti. Pokojne môžeš písať program s tým, že každá dátová štruktúra je dynamicky alokovaná a zdieľaná, fungovať to bude a nemusíš nič prepisovať. Je to efektívne? Nie. Ale efektivita nie je zadarmo, musíš o nej niečo vedieť a niečo pre ňu urobiť. Existuje programovací jazyk, ktorý dáva tieto možnosti automaticky a človek pre to nemusí nič urobiť? Ja neviem, rád sa niečo nové naučím, ale dosť o tom pochybujem.
A potom, ktorý rozumný programátor by používal C++, keď nepotrebuje možnosti, ktoré C++ poskytuje?
U naprosté většiny objektů nepotřebuju řešit, zda bude sdílen či ne, kdy skončí životnost apod. Dokonce je to tak, že díky tomu, že tyto věci není potřeba vyhodnotit, tak to vede na jednodušší algoritmus a kód.
Dále, ať už je objekt takový či makový, nemá to vliv na hlavičku funkce, do které ho chci poslat. To samozřejmě výrazně usnadňuje vývoj, údržbu, předělávky atd.
To že v C++ musím dělat tato rozhodnutí pro každou jednotlivou instanci a každý jednotlivý parametr je samozřejmě vlastnost C++ (nenazýval bych to až tak chybou), v jazycích jako java to pro většinu instancí není nutné.
Další faktor je, že z mnoha důvodů je dobré mít konstantní objekty (abych nemusel řešit to sdílení apod.). To ovšem vede na vyšší nároky na alokátor, jenže založit objekt je v C++ výrazně dražší než třeba v JVM. To opět zvyšuje pravděpodobnost, že toho programátor v C++ bude muset řešit víc než je nutné jinde.
> Pokojne môžeš písať program s tým, že každá dátová štruktúra je dynamicky alokovaná a zdieľaná, fungovať to bude a nemusíš nič prepisovať
To samozřejmě fungovat nebude, stačí mít mezi objekty cyklus a už nemůžu použít shared_ptr. Pokud ho nepoužiju, musím řešit vlastnictví. A už se to veze...
> efektivita nie je zadarmo, musíš o nej niečo vedieť a niečo pre ňu urobiť
Anebo můžu použít platformu, která 95% těch situací vyřeší sama a já se zatím můžu zabývat tím co chci řešit já.
> U naprosté většiny objektů nepotřebuju řešit, zda bude sdílen či ne, kdy skončí životnost apod.
Keď niečo neriešiš osobne, tak to za teba vyrieši niekto iný a je otázka, či ti to tak vyhovuje. Mne nie.
> Dále, ať už je objekt takový či makový, nemá to vliv na hlavičku funkce, do které ho chci poslat.
To aký je objekt nie, to ani nikto netvrdí. Vlastníctvo a pod. neriešime kvôli samotnému objektu, ale kvôli tomu, ako s ním pracujeme. Vo funkciách. Riešime, či je objekt vo funkcii vytvorený a vrátený volajúcemu, alebo či z prijatého objektu vo funkcii iba čítame alebo ho aj modifikujeme alebo objekt kompletne nahradíme iným objektom, alebo či ten objekt vo funkcii končí svoju životnosť, v iných prípadoch je naopak rozumné zabezpečiť, aby objekt počas volania funkcie nezanikol, atď. (Nepochybujem, že toto vieš aj sám.) A podľa toho akú požadujeme funkčnosť volíme argumenty funkcií.
> To že v C++ musím dělat tato rozhodnutí pro každou jednotlivou instanci a každý jednotlivý parametr
Stále si myslím, že to naozaj nemusíš. Môžeš sa správať na základe štandardných odporúčaní, teda opakovať stále jedno počiatočné rozhodnutie pre daný kontext, a v odôvodnených prípadoch sa môžeš rozhodnúť pre niečo iné. Keď vieš, že za to získaš niečo, čo potrebuješ.
> jenže založit objekt je v C++ výrazně dražší než třeba v JVM
S JVM nepracujem, tak neviem ako to myslíš, ale keď chcem, aby som mal v C++ objekt vytvorený rýchlo, čo sa týka objektov, ktorých mám v aplikácii kvantum, tak si odhadnem koľko ich asi budem mať, predalokujem pamäť pre všetky naraz (zjednodušene povedané), vytvorím vlastný "alokátor" a vytvárané objekty budú existovať v rámci predalokovanej pamäťovej oblasti. Keď chcem, tak tú oblasť môžem mať inicializovanú blokom objektov načítaných z disku, alebo iba namapovanú zo súboru, na základie služieb OS. Takže vo finále vytvorenie jedného objektu je vlastne práca s ukazovateľom a s nejakou internou dátovou štruktúrou, v ktorej je evidencia voľných a obsadených blokov (zoznam, strom, bitová mapa, čokoľvek iné), prípadne ešte inicializácia jednotlivých členských premenných vytváraného objektu, pokiaľ ich naozaj vytváram a neboli načítané alebo namapované. Uvoľnenie jednotlivej položky je ešte jednoduchšie a uvoľnenie celého bloku ani nemusím písať. Fragmentácia nula. JVM má nejakú rýchlejšiu/lacnejšiu metódu?
> ... že toho programátor v C++ bude muset řešit víc než je nutné jinde.
Naozaj zďaleka nie vždy a pokiaľ za to dostane niečo, čo inde nie, tak v tom nevidím problém.
> To samozřejmě fungovat nebude, stačí mít mezi objekty cyklus
Nechápem.. Myslíš cyklus ako for, while, atď? Tu neviem, čo napísať, už dávno používam štandardné algoritmy.
Alebo myslíš dva objekty, ktoré na seba vzájomne držia ukazovateľ? O tom sa ale nebavíme, reagoval som na zmienku o argumentoch funkcií. A pokiaľ nechceš, aby sa inkrementoval počet, tak ten zdieľaný ukazovateľ odovzdáš odkazom.
Alebo môžeš do funkcií posielať holý ukazovateľ. Aj tak nechceš riešiť vlastníctvo, tak je to jedno, nie? :)
> Anebo můžu použít platformu, která 95% těch situací vyřeší sama
To samozrejme môžeš, ale vtedy asi nespadáš pod definíciu poslednej vety môjho komentára, pretože tam spadá tých "5%" vecí, ktoré sa samé nevyriešia.
Vo finále nechápem o čom sa bavíme, možno iba nepatríš medzi tých, ktorí vlastnosti C++ potrebujú. Ale to je úplne v poriadku.
> Vo finále nechápem o čom sa bavíme
Původně jsem vysvětloval MarSikovi tvrzení, že C++ má náročnou správu paměti. Tvůj příspěvek to dokresluje naprosto skvěle.
Vytváření vlastních alokátorů je věc, kterou jsem viděl mockrát, dokonce jsou jedinci (i přítomni v této diskuzi), kteří se tím chlubí. Ukazuje to, jak je správa paměti v C++ špatná.
> JVM má nejakú rýchlejšiu/lacnejšiu metódu?
Samozřejmě, posune pointer a vrátí původní hodnotu, je to zhruba na 2 instrukce.
> Alebo myslíš dva objekty, ktoré na seba vzájomne držia ukazovateľ? O tom sa ale nebavíme,
O tom se musíme bavit. V C++ prostě nemůžeš automaticky vše udělat shared a doufat, že to bude fungovat. A nemůžeš vše jen tak předávat raw pointerem, protože pak nevíš, kdy to zmizí. Tvůj návrh prostě nelze korektně realizovat.
Ja suhlasim z predoslim prispevkom (od zulu). To, ze sa programator moze rozhodnut kam da objekt ci na haldu alebo heap je neskutocna vyhoda a nie len v perfomace.
V Jave (a inych GC jazykoch) je vetyvornie objektu stale drahsie ako jeho vytvorenie na halde v C++ a to niekolko nasobne a nie je to len pusnutie pointera. (C# to riesi tym, ze vies pouzit struktury, ktore su na zasobniku, alebo direktivou stackalloc).
>O tom se musíme bavit. V C++ prostě nemůžeš automaticky vše udělat shared a doufat, že to bude fungovat. A nemůžeš vše jen tak předávat raw pointerem, protože pak nevíš, kdy to zmizí. Tvůj návrh prostě nelze korektně realizovat.
To napriklad Qt riesi elegantne registraciou v "parent" objekte.
Ono tie vycitky vysie na spravu objektov v C++ pramenia z jeho absolutnej neznalosti a neznalosti novych srandardov. V nich sa o spravu pameti clovek nemusi starat skoro vobec. Staci pochopit tu fylozofiu.
> To, ze sa programator moze rozhodnut
Znovu opakuji - ne že se může rozhodnout. On to rozhodnutí _musí_ dělat pokaždé u každé instance. To je poněkud rozdíl.
> V Jave (a inych GC jazykoch) je vetyvornie objektu stale drahsie ako jeho vytvorenie na halde v C++
Lze snadno vyvrátit benchmarkem. Mě vyšla průchodnost JVM asi desetinásobná oproti C++ v MSVC. Pokud si dobře pamatuju, C++ dokázalo alokovat nižší desítky milionů objektů za sekundu, JVM byla na stovkách.
> To napriklad Qt riesi elegantne registraciou v "parent" objekte.
A co když něco jako "parent" neexistuje? To tam pak musím uměle dodat? Pokud to jsou GUI komponenty, tak je to jasné, ale jsou datové struktury, kde jeden parent není.
> z jeho absolutnej neznalosti a neznalosti novych srandardov. V nich sa o spravu pameti clovek nemusi starat skoro vobec. Staci pochopit tu fylozofiu.
Jasně. A pak to změříš a zjistíš, že je to pomalé a necháš standardy standardama.
> V Jave (a inych GC jazykoch) je vetyvornie objektu stale drahsie ako jeho vytvorenie na halde v C++ a to niekolko nasobne a nie je to len pusnutie pointera. (C# to riesi tym, ze vies pouzit struktury, ktore su na zasobniku, alebo direktivou stackalloc).
Citation needed. Zni to spis jako tvuj pocit, protoze to neni pravda :-)
Napr. jeden microbenchmark (nutno dodat, velmi stary): https://blog.cfelde.com/2010/06/c-vs-java-performance/
Samozrejme hodne zalezi na konkretnim use case, obecne jsou situace kdy C++ alokace je rychlejsi a kde alokace JVM je rychlejsi, ale to co tvrdis je pitomost, protoze nekolikanasobne pomalejsi alokace v Jave proste obecne neni vuci C++.
> Původně jsem vysvětloval MarSikovi tvrzení, že C++ má náročnou správu paměti. Tvůj příspěvek to dokresluje naprosto skvěle.
To je tvoj osobný názor, pravdepodobne na základe toho, že nepotrebuješ komplexnú funkčnosť a stačí ti obmedzená sada.
> Samozřejmě, posune pointer a vrátí původní hodnotu, je to zhruba na 2 instrukce
A dostaneš tým tú istú funkčnosť? Objekt alokovaný v rámci sady objektov v bloku alokovanom naraz a uvoľnenom naraz, držanej lokálne v jednej oblasti pamäti, prípadne úplne spojito a bez medzier (až na prípadné zarovnanie)? Alebo si myslíš, že to sú veci, za ktoré nie je nikto ochotný zaplatiť? A aj rýchlosť? A to všetko na 2 inštrukcie? Porovnávame naozaj porovnateľné?
> O tom se musíme bavit.
Nie. O tom by sme sa teoreticky mohli baviť, keby som reagoval na tento kontext. Ja som reagoval na hlavičky funkcií.
> V C++ prostě nemůžeš automaticky vše udělat shared a doufat, že to bude fungovat
Ja to tak samozrejme nerobím, nijako ma neobťažuje deklarovať veci podľa potreby. Paradoxne, rebase kvôli tomuto naozaj nerobievam. Ale ak to niekoho obťažuje, nevidím dôvod prečo by to v hlavičkách funkcií nefungovalo.
A keď by sme sa teda mali baviť o dátových štruktúrach s cyklickými odkazmi, tak máme silné ukazovatele a slabé ukazovatele.
> A nemůžeš vše jen tak předávat raw pointerem, protože pak nevíš, kdy to zmizí.
Všimol si si, že o holých ukazovateľoch píšem v kontexte, že neriešiš životnosť? Písal si to v príspevku, na ktorý reagujem. Tak prečo ju riešiš teraz?
Odhliadnuc od toho, zmizne "to" vtedy, keď to uvoľníš. Alebo keď ukazovateľ prepíšeš iným obsahom. Keď to neuvoľníš a keď ukazovateľ neprepíšeš, tak to nezmizne.
Základný problém v správe pamäti ale nie je ani tak to, že niečo zmizne, keď nechceš, aby to zmizlo, ale to, že niečo nezmizne vtedy keď už nechceš, aby to existovalo, teda napríklad pri neošetrenej výnimke.
Ale aj táto časť debaty je v podstate zbytočná, pretože vyššie som spomenul, že vo väčšine prípadov použiješ odporúčania, ktoré už nejaký čas sú v zmysle čo najviac objektov v zásobníku s ich automatickou deštrukciou, odovzdávanie odkazom, prípadne presunutie do volanej funkcie a používanie toho istého mechanizmu v rámci RAII.
> To je tvoj osobný názor, pravdepodobne na základe toho, že nepotrebuješ komplexnú funkčnosť a stačí ti obmedzená sada.
To je na základě toho, že jsem si pár algoritmů zkusil napsat v C++ i v javě a zjistil jsem, že abych dostal v C++ lepší výkon, tak jsem musel řešit asi 10x víc věcí, optimalizovat atd. V javě lze z pohledu C++ proramátora dost prasit (čti využívat funkcionální principy jako konstantní objekty atd.), což sice vede na větší zátěž VM, ale ta je na to optimalizovaná a programátor se většinou může spolehnout, že to dopadne dobře.
Samozřejmě jsou extrémní případy, kdy je nutný low level jazyk, ale v praxi se spíš setkávám s takovými C++ programátory, kteří optimalizují každou ptákovinu aniž vědí proč a bojí se, že by o to v javě přišli.
Konkrétně jsem jeden takový C++ kód předhodil v jedné diskuzi a první co matlal udělal bylo, že přepsal předávání všech struktur na const &. Sice to na výkonu nezměnilo ani prd, ale měl z toho dobrý pocit.
> Konkrétně jsem jeden takový C++ kód předhodil v jedné diskuzi a první co matlal udělal bylo, že přepsal předávání všech struktur na const &. Sice to na výkonu nezměnilo ani prd, ale měl z toho dobrý pocit.
A zeptal ses, proč to udělal? Ono to IMO nebylo primárně kvůli výkonu. V c++ je idiomatické předávat const & vždycky když nemáš nějaké speciální požadavky. Stejně tak je idiomatické vracet hodnotou a ne jako pointer na nově alokovaný objekt. Pak v obou případech nemusí autor funkce opravdu řešit, jestli ty objekty budou na zásobníku nebo na haldě.
> A zeptal ses, proč to udělal? Ono to IMO nebylo primárně kvůli výkonu...
Neptal jsem se. Úkol byl urychlit to, takže předpokládám, že si myslel, že se to tím zrychlí. Prostě takový ten každodenní cargo cult, který u zažraných C++ programátorů vidím každou chvíli. Je nezajímá, že mají algoritmus O^4, oni chtějí ušetřit na předávání reference.
Přijde ti v pořádku argumentovat tím, že mě cituješ slovy, které jsem nevyslovil?
Řekl jsem, že je to matlal. Když někomu dám urychlit kus kódu (jednorázový, testovací), on tam udělá mraky změn ale přitom neurychlí vůbec nic, tak to splňuje definici matlala ať už jsou jeho záměry sebevznešenější. To znamená, že nemá smysl se ho ptát na důvody, protože případná odpověď nemá vliv na fakt, že řešil něco jiného než řešit měl.
A tento příklad dobře ukázal, jak je programátor odváděn od problému a místo toho řeší specifika daného jazyka.
> Přijde ti v pořádku argumentovat tím, že mě cituješ slovy, které jsem nevyslovil?
Jak slovy, které jsem nevyslovil? Když ve svém textu nahradím "pitomec" za "matlal", tak mám skoro doslova to, co jsi tu napsal.
Skoro se bojím hádat, jak mohlo vypadat to zadání. Podle toho, co tady kolem píšeš se bojím, že jsi typicky po Javovsku naalokoval mračna malých objektů (odhaduju podle poznámky o dynamicky alokovaném 3D vektoru). Pak se to zamozřejmě urychlit nedá. Tam není problém rychlost jazyka. Tam je problém, že žádné CPU nezvládá kód, který skáče po paměti jako divý. Tenhle přístup trestají všechny jazyky +- stejně, protože cache miss stojí +- stejně.
> čti využívat funkcionální principy jako konstantní objekty atd
To sa predsa dá aj v C++
Okrem toho, šablónové metaprogramovanie je vlastne funkcionálne programovanie
> Samozřejmě jsou extrémní případy, kdy je nutný low level jazyk
Stačí ak píšeš pre platformu, ktorú nemáš pod kontrolou a pre ktorú nemáš inú možnosť.
> s takovými C++ programátory, kteří optimalizují každou ptákovinu
To sa týka programátorov, nie jazyka, takí sú všade a v každom obore :-)
> a bojí se, že by o to v javě přišli
Nemusí ísť iba o jazyk samotný, ale aj ekosystém, knižnice, atď., je v tom veľa know-how, ktorý sa neoplatí zahodiť len kvôli tomu, že sa niečo môže zdať niekomu nepohodlné.