Go vs. Rust - System Programming languages - Umfrage



  • Marthog schrieb:

    Ausserdem entstehen die meisten Fehler durch dangling pointer, dereferenzieren von Null-pointern oder ungueltige Iteratoren.

    Betrifft mich nicht mehr.



  • Das ist für mich erstmal irrelevant. Ich hab ja nicht behauptet, dass C++ perfekt wäre. Nur werde ich mir ohne guten Grund nicht einfach so irgendwelche neuen Sprachen anschauen. Und das sind keine guten Gründe. Man kann mit C++ gut genug arbeiten und sicher programmieren. Man braucht schon irgendwelche Killerfeatures, um auf eine neue Sprache umzusteigen. Und eine experimentelle Sprache, bei der es kaum Libraries, Tools, Beispiele, Best Practices usw. gibt, und die sich mit hoher Wahrscheinlichkeit nie durchsetzen wird interessiert mich eben nicht.
    Das ist aber alles nur meine subjektive Meinung. In der IT entwickelt sich vieles recht schnell und man kann natürlich nicht ewig beim alten bleiben. Ich könnte mir schon vorstellen, dass viele erstmal zumindest privat auf den Rust Zug aufspringen. Nur ist eine Programmiersprache für mich eher ein Werkzeug, dass ich nur sehr ungern wechsle. Für mich ist wichtiger, mich da subjektiv wohler zu fühlen, weil ich mich gut auskenne, als irgendwelche Features, die auf dem Papier Sinn machen.



  • Das kann ich gut nachvollziehen. Es ist nur zur Zeit so, dass neue Prozessoren zunehmend statt auf Taktrate auf Mehrkern setzen und ich vermute, dass der Trend in Zukunft eher zunimmt.
    Die alten Programmiersprachen sind fuer Multithreading aber kaum ausgelegt, Rust hingegen schon. Ich finde die Vorstellung sehr angenehm, Multithreading effizient auszunutzen ohne sich dafuer mit dem Low-Level-Kram herumschlagen zu muessen.



  • Marthog schrieb:

    Die alten Programmiersprachen sind fuer Multithreading aber kaum ausgelegt, Rust hingegen schon. Ich finde die Vorstellung sehr angenehm, Multithreading effizient auszunutzen ohne sich dafuer mit dem Low-Level-Kram herumschlagen zu muessen.

    Ich hatte solche Probleme auch noch nie wirklich. Glaube auch nicht, dass hier die Sprache vorrangig wäre. Wir entwickeln eine sehr große Software im CAD/PDM Bereich, die alles mögliche macht. z.B. 3D Modelle generieren, oder Features in Meshes erkennen, oder Meshes reparieren usw., also durchaus rechenintensiv. Als ich angefangen habe, war praktisch alles noch single threaded. Mittlerweile haben wir vieles umgebaut und können für rechenintensive Aufgaben auch mehrere Threads auslasten. Und das funktioniert auch in C++. War vielleicht nicht ganz einfach, paar komische Probleme haben wir schon etwas länger untersuchen müssen, paar sind erst beim Kunden aufgefallen. Aber erstens glaub ich nicht, dass es mit Rust komplett problemlos gelaufen wäre und sofort perfekt funktioniert hätte. Und zweitens ist die ganze Software einfach viel zu groß und zu komplex, um sie wegen irgendwelcher Sprachfeatures wie "bessere Multithreading Unterstützung" in einer anderen Sprache zu schreiben. Ich mein, auf eine andere Sprache portieren ist sowieso unmöglich, würden wir nie schaffen. Aber ich würd mich auch nicht trauen, sowas großes in einer neuen Sprache anzufangen, die noch nicht so etabliert ist. Kommt natürlich auch wieder der Punkt, dass wir zig 3rdparty Bibliotheken verwenden (Open Source und kommerziell) und da natürlich auch wieder eine Sprache brauchen, die entsprechend verbreitet ist.



  • Es hat keiner behauptet, dass man ein schon existierendes Projekt in Rust übersetzen sollte. Die Mozilla-Entwickler fangen z.B. bei ihrer HTML-Render Engine komplett von vorne an und denken dabei gleich daran, wie man das im Zuge von No-Free-Lunch vernünftig parallelisieren kann. Die Zahl der Leute, die Rust zur Zeit produktiv einsetzen, ist sehr klein. Dazu ist das alles noch zu neu. Bei Mozilla läuft das als "Research Projekt".

    Aber hier nur von "theoretisch interessant" zu sprechen, würdigt die Sache IMHO nicht genug. Rust soll natürlich praktische Probleme lösen. Das Lebenszeitsystem und der Borrow-Checker erlauben nochmal ein ganz anderes Level an Sicherheit, was man Benutzern als Bibliotheksautor bieten kann. Die Standardbibliothek geht da mit gutem Beispiel voran. Ich kann mir aber vorstellen, dass man das nicht zu schätzen weiß, wenn man es nicht kennen gelernt hat. Viele C Programmierer haben ja auch noch nichts von RAII gehört und können sich darin keinen Nutzen vorstellen... 😉

    Und dass man als C++ Programmierer die Syntax ( typename allocator::template rebind<T>::type ), die Adhoc-Templates (Concepts lassen auf sich warten), Headerdateien (Module lassen auf sich warten), die allgemeine Komplexität (siehe z.B. Meyers C++ Talk auf der D Konferenz) und allerlei Fallstricke (z.B. Dreierregel) so gut findet, kannst du mir nicht erzählen. Wir arrangieren uns nur irgendwie damit. Müssen wir. Weil wir noch keinen besseren Ersatz haben. Noch nicht. Das ist aber kein Grund, die Schwächen von C++ wegzufantasieren. Natürlich wird Rust auch nicht perfekt werden. Abes es kommt mir doch aktuell so vor, als sei es weit aus eleganter, einfacher und sicherer.



  • volkard schrieb:

    Marthog schrieb:

    Ausserdem entstehen die meisten Fehler durch dangling pointer, dereferenzieren von Null-pointern oder ungueltige Iteratoren.

    Betrifft mich nicht mehr.

    Das ist schön für Dich. Heißt dann aber wahrscheinlich auch, dass Du Deinen Kram ganz alleine machst. Denn so viele C++ Programmierer, die nie einen Fehler in der Richtung machen, gibt's nicht.



  • Mich nervt's, daß immer Sprachen rumerfunden werden, die dann groben Anfängerfehler adressieren. Nullzeiger dereferenzieren ist so einer. Der passiert in der Praxis wirklich nicht. Und da stehe ich nicht alleine. Sowas als "Die meisten Fehler" kann Anfänger bezeichnen.
    Lustige GCs bauen, weil man in C viel Aufwand hatte, an jedes close() und free() zu denken. Sprachen mit GC schaue ich nicht mehr an, davon gibt es genug.



  • volkard schrieb:

    passiert in der Praxis wirklich nicht.

    Schau mal hier, wieviele von den Sicherheitsproblemen bei Firefox Probleme sind, die in der Praxis "nicht wirklich" auftreten. Das sieht bei Google Chrome im übrigen genauso aus. Ein Großteil dieser Probleme sind Speichersicherheits-Probleme. Und genau das wird bei Rust adressiert. Aber von mir aus kannst du Deinen Kopf weiter im Sand stecken lassen. 😉

    volkard schrieb:

    Lustige GCs bauen, weil man in C viel Aufwand hatte, an jedes close() und free() zu denken. Sprachen mit GC schaue ich nicht mehr an, davon gibt es genug.

    Ich tendiere dazu, es ähnlich zu sehen. Aber ich bilde mir nicht ein, alle Anwendungsdomänen zu überblicken. Das heißt, dass ich nicht davon überzeugt bin, dass Garbage Collection immer eine schlechte Idee ist. Ich bin bisher nur immer ohne in C++ ausgekommen. Das ist auch mit ein Grund dafür, dass ich mir Rust statt D oder Go angeguckt habe. Rust ist im Wesentlichen wie "gezwungenes modernes C++" mit der Extra-Garantie, dass "Sharing" und "Mutation" nicht gleichzeitig auftreten können ( &mut T , der Typ für Referenzen, über die man etwas verändern kann, impliziert quasi restrict , was zur Compilezeit auch gecheckt wird). Das ist ein wichtiges Konzept in Rust. Und so etwas wie new[] / delete[] gibt's da gar nicht. Man muss stattdessen Vec benutzen (oder einen unsafe -Block aufmachen, aber das stellt schon eine gewisse Hürde dar): D.h. alles ist voll von RAII. Und man kann eben nicht ohne einen gewissen Aufwand ( unsafe ) Scheiße bauen. Beispiel:

    fn main() {
        let p: &int;
        {
            let mut v = vec![1,2,3,4i];
            {
                let x = v.get(2); // x ist ein Zeiger auf das 3. Element
                                  // Ist der Index ungültig, bricht der "Task"
                                  // ab, wobei ein ordentliches "stack unwinding"
                                  // statt findet. Oft gibt es aber auch andere
                                  // Funktions-Varianten, die weniger "brutal" sind
                                  // und stattdessen im Fehlerfall etwas anderes
                                  // zurückgeben können.
                println!("Das 3. Element ist {}", *x);
    
                //v.push(5); // könnte zu einer Reallokation führen. Aber der Vektor
                             // gilt wegen x als "ausgeliehen". Deswegen ist diese
                             // modifizierende Operation nicht zugelassen. Der Compiler
                             // bekommt das mit und würde eine Fehlermeldung ausgeben.
                             // Das ist gut so, weil sonst x ein baumelnder Zeiger
                             // werden könnte.
    
                //p = x; // wird auch nicht zugelassen, weil p länger als der Vektor
                         // lebt und p damit ein baumelnder Zeiger werden würde.
            } // <-- Ausleihen des Vektors hier zu Ende
            v.push(5); // Jetzt klappt's wieder!
        } // <-- hier endet die Lebenszeit des Vektors
    } // <-- hier endet die Lebenszeit von p
    

    Der Compiler kann die auskommentierten Fehler abfangen, weil die Lebenszeiten Teil des Typsystems sind und als Compilezeit-Metainformationen bei allen Referenztypen mit dranhängen (und meist deduziert werden) und weil im Compiler ein "Borrow Checker" überprüft, ob das, was an da so hinschreibt überhaupt legal nach den Rust-Regeln ist. Natürlich ist das ein künstliches Beispiel, was keiner so aufschreiben würde. Aber ich wollte hier mal skizzieren, wie Rust die versprochene "Memory-Safety" garantieren kann, ohne auf Garbage Collection zu setzen. Das mit den Lebenszeiten wurde nicht erst für Rust erfunden. Es basiert auf den "region pointers" der Sprache Cyclone.

    Genauso, wie mir C wegen nichtexistierender Unterstützung für RAII oder Templates primitiv vorkommt, kommt mir inzwischen C++ wegen nichtexistierender Lebenszeiten im Typsystem primitiv vor.



  • Was exakt ist eigentlich der Grund dass hier so gegen GCs gehetzt wird? Der Performance ist gleich gut bis besser, die Vorteile liegen auf der Hand.

    Irgendwie geht es immer nur um die deterministische Freigabe von Resourcen (die ich fast nie benötige und wenn dann lässt sich das auch in GC-Sprachen mit minimalem Aufwand machen, zb. try with resources) oder um die Echtzeit-Tauglichkeit die einerseits bei den meisten Applikationen uninteressant ist (und wofür vermutlich auch C++ eher ungeeignet ist) und andererseits nichtmal stark beeinträchtigt ist. Wenn zb. der Java GC anspringt sieht man keinen signifikanten Einbruch - wenn man nicht gerade für Android & Dalvik entwickelt.

    Perfekt ist in meinen Augen das Modell von C#: GC und trotzdem zusammengesetzte Werttypen.



  • Ethon schrieb:

    die ich fast nie benötige und wenn dann lässt sich das auch in GC-Sprachen mit minimalem Aufwand machen, zb. try with resources

    Da haben wirs.
    Wieso möglichen Laufzeitoverhead und minimalen Aufwand, wenn man dasselbe für minimalen Aufwand ohne möglichen Laufzeitoverhead* haben kann?

    *gut, exception handling kann da evtl. auch Overhead reinmachen 🙄



  • Ethon schrieb:

    Der Performance ist gleich gut bis besser, die Vorteile liegen auf der Hand.

    Nein und nein.



  • Ethon schrieb:

    Was exakt ist eigentlich der Grund dass hier so gegen GCs gehetzt wird? Der Performance ist gleich gut bis besser, die Vorteile liegen auf der Hand.

    Ich fühl mich dabei jetzt nich so richtig angesprochen. Habe während des Studiums und ein bisschen danach, viel Java gemacht. Aber seit dem ich zu C++ gewechselt habe, habe ich nie einen GC vermisst. Und da frag ich mich schon, warum ich mir so etwas ans Bein binden soll, wenn ich es doch nicht brauche. Mag ja sein, dass Du ganz andere Anwendungsfälle hast ... Dagegen sag' ich ja auch nichts ...

    Als D Fan interessiert dich vielleicht, dass jemand D für einen JavaScript JIT Compiler verwendet hat und neulich bemerkte, dass 75% der Laufzeit für Allokation/Garbage Collection drauf gehen, weil die aktuelle Implementierung quadratisch viel Zeit in der Zahl kleiner Objekte "verbrät". Ist also zumindest verbesserungswürdig. Garbage Collection bedeutet bewiesenermaßen ein Zielkonflikt zwischen Speicheraufwand und Zeitaufwand. Meist wird sowas zugunsten der Performance implementiert, was dann 2-5fachen Speicheroverhead bedeuten kann.



  • Ethon schrieb:

    Was exakt ist eigentlich der Grund dass hier so gegen GCs gehetzt wird? Der Performance ist gleich gut bis besser, die Vorteile liegen auf der Hand.

    GCs ohne Generations (oder ähnliche Konstrukte) sind langsam, weil sie bei jeder Collection alle Objekte durchackern müssen. Bei Programmen mit einem grossem Working-Set welches sich aus vielen kleinen Objekten zusammensetzt braucht das viel Zeit.

    GCs mit Generations sind schneller, dafür müssen sie über das Ändern von Referenzen Buch führen. Was auch nicht gratis ist - alle Schreibzugriffe auf Referenzen werden dadurch langsamer.

    GCs die kompaktieren verbraten beim Kompaktieren Zeit. Umso mehr je mehr Objekte es gibt, weil alle Referenzen auf verschobene Objekte umgeschrieben werden müssen. (Und natürlich müssen die Objekte auch verschoben werden, was aber wenn ich mich richtig erinnere eher weniger ins Gewicht fällt.)

    Und GCs die nicht kompaktieren brauchen erst wieder eine Freelist und müssen diese warten und bei Allokationen darin suchen. Was einen wichtigen Punkt wo der GC aufholen kann wieder zunichte macht.

    In Summe kann sich das vermutlich je nach Programm so oder so auswirken. Pauschal zu sagen der GC wäre "gleich schnell oder schneller" halte ich aber für falsch.



  • ps:

    Ethon schrieb:

    Irgendwie geht es immer nur um die deterministische Freigabe von Resourcen (die ich fast nie benötige

    Also ich brauch' das dauernd. Wirklich, dauernd.
    Und wenn ich mir C# Code von anderen Programmierern so ansehe (z.B. Code von Kollegen, Zeugs was im Internet rumflattert etc.), dann finde ich da auch haufenweise fehlende "using" Blöcke (using=das C# "Original" zu try-with-resources).

    ps: Was passiert wenn man nach dem Motto "muss nicht deterministisch freigegeben werden, ist ja im Endeffekt eh nur Speicher" arbeitet, das sieht man bei WPF. WPF + D3DImage + öfter mal die Direct3D Surface wechseln = OutOfMemoryException. Suba, danke ihr tollen "GC is voll kuhl und wir sind voll schlau" Entwickler!!1elf 👍
    Und natürlich hatte ich auch noch niiiiiemals ein Java oder C# Programm das mir ein File offen gehalten hat nachdem ich das entsprechende Dokument im Programm bereits geschlossen hatte. Nein, ehrlich, niiiiiie.



  • Ich füchte, wenn dem C++-Compiler erlaubt wäre, optimierend bei der letzten Verwendung einer Variablen das move automatisch einzufügen, bräuchte ich kein rust.
    Zur Zeit nervt es mich unendlich, daß ich nachdenken muss, wann ich eine Variable wegmoven sollte und wann nicht.

    Damit wäre ich satt. Noch sind mir auch 256 Prozessorkerne recht egal.

    Denke, rust ist der maßgebliche Wegbereiter für eine kommende Messias-Sprache, die dann für sehr sehr lange Zeit was taugt.



  • volkard schrieb:

    Ich füchte, wenn dem C++-Compiler erlaubt wäre, optimierend bei der letzten Verwendung einer Variablen das move automatisch einzufügen, bräuchte ich kein rust.

    Das wurde sogar mal vorgeschlagen. Aber dann sind Code-Beispiele aufgetaucht, die mit so einer Regel nicht mehr das tun würden, was sie sollen. Du brichst also ggf alten Code damit. Das ist noch gar nicht lange her. Findest Du bestimmt irgendwo in 'nem Mailarchiv von isocpp.org oder so. Nachdem derjenige, der das vorgeschlagen hatte, die Beispiele gesehen hatte, zog er seinen Vorschlag wieder zurück.

    volkard schrieb:

    Zur Zeit nervt es mich unendlich, daß ich nachdenken muss, wann ich eine Variable wegmoven sollte und wann nicht.

    Echt? Wie kommt's? Kannst du das eingrenzen? Beschränkt sich das auf generischem Code, den Du schreibst? Denn da könnte std::forward auch nicht ganz unpraktisch in einigen Fällen sein. Zum Beispiel wird im Move-Constructor von std::tuple std::forward verwendet, weil so ein T auch eine Referenz sein könnte und andernfalls unbeabsichtigt etwas gemovet werden könnte:

    string x = "hello";
    string y;
    tie(y) = tie(x); // dies sollte x NICHT verändern obwohl tie(x)
                     // ja ein Rvalue vom Typ tuple<string&> ist.
    

    Ich kann mich jedenfalls nicht an Situationen erinnern, wo die Frage, ob ich std::move oder std::forward benutzen sollte oder nicht, schwierig zu beantworten gewesen wäre. Allerdings habe ich bestimmt auch ein Jahr vorher gebraucht, um die Details von Rvalue-Referenzen komplett zu verstehen.

    volkard schrieb:

    Denke, rust ist der maßgebliche Wegbereiter für eine kommende Messias-Sprache, die dann für sehr sehr lange Zeit was taugt.

    Ahja.



  • Hab noch schöne C++ Beispiele bzgl Speichersicherheit gesehen:
    https://www.reddit.com/r/programming/comments/2ghl3o/the_road_to_rust_10/ckjpd7p



  • neue infos zu rust:

    We plan to ship the 1.0 beta around the end of the year. If all goes well, this will go on to become the 1.0 release after the beta period:
    http://blog.rust-lang.org/2014/09/15/Rust-1.0.html



  • volkard schrieb:

    Lustige GCs bauen, weil man in C viel Aufwand hatte, an jedes close() und free() zu denken.

    Das ist sehr stark vereinfacht! Mehrfache frees sind auch ein Problem. Klar, das Problem kannst du umgehen, wenn du eine Variable nach einem free auf NULL setzt, aber das ist Symptombehandlung und bläht den Code auf.
    Gerade wenn du geteilte Ressourcen hast und auch noch multithreaded, wird das mit der Speicherverwaltung zunehmend komplizierter.
    Oder du machst

    int *x = malloc(...);
    ...
    x = malloc(...);
    ...
    free(x);
    

    Den Memoryleak übersehen viele gerade bei längerem Code. Nee, gerade du solltest es wissen, dass Memoryleaks nicht nur dadurch entstehen, in dem man am Funktionsende ein free() oder close() vergessen hat und die Changelogs von bekannten größeren Projekten wo Profis programmieren, verdeutlichen auch, dass das kein Problem von gestern oder von Anfängern ist. Das geht vom Linux-Kernel bis zum Google Chrome Browser!

    L. G.,
    IBV



  • Also erstmal ist es auch in C nicht wirklich so schwer Resourcen korrekt zu verwalten. Es ist bloss aufwendig und man benötigt dafür recht viel Disziplin.

    Ich glaube aber dass volkard darauf nicht hinauswollte.
    Sondern eher darauf dass wir ja jetzt C++ haben, wo man Dinge wie RAII wunderhübsch einfach machen kann.


Anmelden zum Antworten