von Java nach C++



  • Man muss (extended) Graphemcluster erkennen und diese umdrehen: www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries (bzw. http://userguide.icu-project.org/boundaryanalysis)

    Deshalb habe ich auch geschrieben, dass UTF8-CPP nichts bringt, weil Codepoints nichtssagend sind. Man kann damit das Encoding konvertieren, aber nicht den String analysieren.



  • idx schrieb:

    Hallo,

    ich bin neu hier und starte direkt mal mit einer Frage.

    Ich komme aus der Java Welt und würde jetzt gerne mit C++ beginnen - auf kurz oder Lang soll da mal ein größeres Spiele Projekt raus werden.

    Ich suche daher ein gute Buch oder Tutorial was nicht bei 0 anfängt, d.h ich habe durchaus Erfahrung mit Programmierung (auch wenn die C Entwickler einen Java Entwicklern gerne belächeln)
    Speziell solche Sachen wie Speicherverwaltung, Pointer und Effektiver Code interessieren mich.
    Was gibt es so für Standard libs oder Funktionen die jeder kennen sollte?
    (Bei Java z.B. dieser ganze Apache Kram - commons oder log4j und solche Sachen)
    Was für Stolperfallen gibt es?

    Vielen Dank!

    Ohne jetzt die 8 Seiten Diskussion gelesen zu haben - ich kann folgende Bücher empfehlen:

    • Der C++-Programmierer: C++ lernen - Professionell anwenden - Lösungen nutzen von Ulrich Breymann
    • Effective C++: 55 Specific Ways to Improve Your Programs and Designs von Scott Meyers


  • Ich sehe schon, UTF8 ist riesiger Bockmist.



  • knivil schrieb:

    Ich sehe schon, UTF8 ist riesiger Bockmist.

    Du laberst Unfug. Mit UTF-16 (wie bei Java und C# verwendet) hast du exakt die gleichen Probleme und noch ein paar mehr. UTF-16 ist ebenfalls ein Variable-Length-Encoding. Bei UTF-8 musst du dich halt bereits bei allen Codepoints größer 0x7F mit beschäftigen, die Wahrscheinlichkeit, dass dein Code getestet ist, steigt also.

    Ja, Unicode ist verdammt komplex, wenn man alle Aspekte behandeln will. Und das völlig unabhängig vom Encoding.



  • Von allen Unicode Encodings, die es im Moment so gibt, ist UTF-8 vermutlich mit Abstand das beste... 😉



  • Sowohl Java als auch Windows NT verwenden UTF-16 hauptsächlich aus Legacy-Gründen, nicht weil es irgendwelche Vorteile hätte. Als Microsoft damals mit der Implementierung von Unicode begonnen hatte, gab es noch gar kein UTF-8 und Unicode war auf 16 Bit beschränkt. Also entschied man sich für UCS-2, aus damaliger Sicht eine nachvollziehbare Entscheidung.

    Dass das Unicode-Konsortium sich einige Zeit darauf entschließt, den Coderaum über 16 Bit hinaus zu erweitern, hat wohl weder Microsoft noch Sun geschmeckt. Jetzt verbindet UTF-16 einfach nur noch die Nachteile von UTF-8 und UCS-4/UTF-32 in einem Format.



  • dot schrieb:

    Von allen Unicode Encodings, die es im Moment so gibt, ist UTF-8 vermutlich mit Abstand das beste... 😉

    Unfug, UTF-32 wird von einer modernen CPU wesentlich schneller verarbeitet, als UTF-8, denn UTF-32 hat kein Variable Lengh Coding und das spart Zeit.

    UTF-32 ist also schneller, aber man bekommt nichts geschenkt, denn es braucht mehr Speicher.



  • UTF-32 = am schnellsten schrieb:

    Unfug, UTF-32 wird von einer modernen CPU wesentlich schneller verarbeitet, als UTF-8, denn UTF-32 hat kein Variable Lengh Coding und das spart Zeit.

    Soso, würd mich sehr interessieren, wieso genau UTF-32 von einer modernen CPU "wesentlich schneller verarbeitet" werden sollte, eben weil es mehr Speicher braucht und Speicherbandbreite heutzutage sehr oft das Bottleneck ist. Zumindest wär mal interessant, zu wissen, was genau du unter "verarbeiten" verstehst, denn ob UTF-32 tatsächlich auch nur den Hauch eines Vorteils haben könnte, hängt wohl sehr stark davon ab, was genau man machen will. Mir fällt ehrlich gesagt auf die Schnelle keine Situation ein, in der UTF-8 gerade auf einer modernen CPU bezüglich Geschwindigkeit zumindest nicht von Nachteil sein sollte...



  • Entschuldigung, ich habe mich wohl falsch ausgedrueckt: UTF ist totaler Bockmist.

    wieso genau UTF-32 von einer modernen CPU "wesentlich schneller verarbeitet" werden sollte

    Hat er doch gesagt: variable Laenge einzelner Zeichen. Damit ist ein zusammenhaengendes Array fuer UTF8 ungeeignet.



  • knivil schrieb:

    wieso genau UTF-32 von einer modernen CPU "wesentlich schneller verarbeitet" werden sollte

    Hat er doch gesagt: variable Laenge einzelner Zeichen. Damit ist ein zusammenhaengendes Array fuer UTF8 ungeeignet.

    "Zeichen" (das was ein Mensch von der Straße drunter verstehen würde) haben auch in UTF-32 variable Länge, es ist lediglich so, dass UTF-32 Code Units (im Moment) direkt auf Unicode Code Points mappen. Das einzige, was UTF-32 dir damit bringt, ist wahlfreier Zugriff auf einzelne Code Points. Dieses praktisch völlig nutzlose Feature (Code Point != Zeichen, wie hier nun bereits mehrfach festgestellt wurde) erkaufst du dir dabei mit wahnwitziger Speicherverschwendung. Wieso ein zusammenhängendes Array für UTF-8 ungeeignet sein soll, will sich mir nicht ganz erschließen, wie würde man den String denn deiner Meinung nach besser speichern, vielleicht als verlinkte Liste von Arrays? Was hätte man davon?



  • Wenn in einen UTF-8 String (a) als Array ablege und ein Zeichen ersetze, kann es passieren, dass ich alle nachfolgenden Zeichen verschieben muss. Das gleiche Problem besteht bei UTF-32 (b), da ein Zeichen auch aus mehreren Einheiten bestehen kann.

    Nun betrachten wir die Haeufigkeit, mit der das Problem auftritt. Ich habe keine Statistik, deswegen schaetze ich: Im Fall (a) tritt es sehr oft auf, Fall (b) im Vergleich selten.

    Dieses praktisch völlig nutzlose Feature (Code Point != Zeichen, wie hier nun bereits mehrfach festgestellt wurde)

    Voellig nutzlos scheint es mir nicht zu sein, gerade was UTF-32 betrifft.

    (Code Point != Zeichen, wie hier nun bereits mehrfach festgestellt wurde)

    Jaja, nur sind die Konsequenzen fuer die unterschiedlichen UTF-Codierungen unterschiedlich.

    wahnwitziger Speicherverschwendung

    Und schon wieder ein Superlativ und masslose Uebertreibung. Ich schaetze, es benoetigt doppelt soviel im Mittel, also fernab von wahnwitzig.

    Um es nochmals herauszuheben, es geht um Stringverarbeitung, d.h. wie es ueber das Netz oder auf der Platte abgelegt wird, war nicht mein anliegen. Das kann gern Utf-8 sein.



  • knivil schrieb:

    Wenn in einen UTF-8 String (a) als Array ablege und ein Zeichen ersetze, kann es passieren, dass ich alle nachfolgenden Zeichen verschieben muss. Das gleiche Problem besteht bei UTF-32 (b), da ein Zeichen auch aus mehreren Einheiten bestehen kann.

    Nun betrachten wir die Haeufigkeit, mit der das Problem auftritt. Ich habe keine Statistik, deswegen schaetze ich: Im Fall (a) tritt es sehr oft auf, Fall (b) im Vergleich selten.

    knivil schrieb:

    Ich schaetze, es benoetigt doppelt soviel im Mittel, also fernab von wahnwitzig.

    Nun, da hast du dir schon ein sehr konkretes Problem ausgesucht. Aber selbst in diesem Beispiel kann ich unter den von dir getroffenen Annahmen im UTF-8 Fall einfach einen zweiten Buffer allokieren, wäre vom Speicherverbrauch her immer noch in etwa gleich unterwegs wie die in-place Variante mit UTF-32, bräuchte im Vergleich aber nur die halbe Bandbreite und müsste auch niemals was nach hinten verschieben... 😉

    knivil schrieb:

    Um es nochmals herauszuheben, es geht um Stringverarbeitung, d.h. wie es ueber das Netz oder auf der Platte abgelegt wird, war nicht mein anliegen. Das kann gern Utf-8 sein.

    Zum Datenaustausch willst du aus allen möglichen Gründen (Endianess Issues, Bandbreitenbedarf etc.) meisten sowieso unbedingt UTF-8 verwenden. Man sollte nicht vergessen, dass du die Daten für eine Weiterverarbeitung in irgendeinem anderen Encoding dann erstmal Transcoden müsstest...



  • knivil schrieb:

    Nun betrachten wir die Haeufigkeit, mit der das Problem auftritt. Ich habe keine Statistik, deswegen schaetze ich: Im Fall (a) tritt es sehr oft auf, Fall (b) im Vergleich selten.

    Ich habe auch keine Statistik.

    Schätzung:

    1. 60% muss nichts verschoben werden, weil beide Zeichen die gleiche Anz. Bytes brauchen (Chinesisch-Chinesisch, Englisch-Englisch)
      2a) 20% braucht der Ersatz weniger Bytes als der vorherige, das geht schön inplace
      2b1) 10% braucht der Ersatz mehr Bytes, aber mehrere Codepoints
      2b2) 10% braucht der Ersatz mehr Bytes, aber nur einen Codepoint

    Sehr oft ist in meinen Augen etwas anderes. Vergleichen wir den Speed, unter der Annahme, dass UTF-8 halb so viel Speicher braucht und Memory das Bottleneck ist.

    1. 60%: UTF-8 ist 2x so schnell wie UTF-32
      2a) 20%: UTF-8 ist 2x so schnell wie UTF-32
      2b1) 10%: UTF-8 ist 2x so schnell wie UTF-32
      2b2) 10%: UTF-8 ist gleich schnell wie UTF-32 (alles kopieren) *

    *: Jetzt lässt sich UTF-8 aber noch auf diesen Fall optimieren. Zum Beispiel alle 8 Zeichen ein Puffer-Nullbyte einfügen, das am Schluss ignoriert wird. Weil wir runden braucht UTF-8 immer noch etwa halb so viel Speicher als UTF-32, aber der Fall 2b2) ist 2x so schnell wie UTF-32.

    Jaja, nur sind die Konsequenzen fuer die unterschiedlichen UTF-Codierungen unterschiedlich.

    Wenn Speicher sehr schnell ist und die CPU sehr langsam und und irgendetwas (!= Sortieren) auf Basis von Codepoints gemacht werden soll (Rendern von Text?), dann ist vielleicht UTF-32 besser.
    Der Hauptvorteil, Random Access auf Codepoints, ist aber so gut wie nutzlos. Vielleicht für rückwärtsiterieren? Einfacher zum Coden, wenn ohne Library?

    Aber schon rein aus Konsistenzgründen ist UTF-8 zu empfehlen, denn für abspeichern sollte man es auf jeden Fall verwenden und internes Konvertieren führt nur zu Bugs.



  • Die Aussage zu 2b2) kommt mir komisch vor. Weiterhin, schaetze ich, ist schreiben von 4 Byte aehnlich schnell wie 1 Byte.



  • knivil schrieb:

    Weiterhin, schaetze ich, ist schreiben von 4 Byte aehnlich schnell wie 1 Byte.

    Mit anderen Worten: Wenn ich mit weniger als 4 Byte auskomme, kann ich in der selben Zeit mehr sinnvolle Daten schreiben... 😉



  • Natuerlich, wenn du deine Schreiboperation in einen Block aus 4 zusammenhaengenden Bytes als "Transaktion" packen kannst. Aber bedenke: All das, auch andere Optimierungen wie Fuellbytes, bringen uns weit weg von std::string als Datenstruktur fuer UTF-8.



  • knivil schrieb:

    Natuerlich, wenn du deine Schreiboperation in einen Block aus 4 zusammenhaengenden Bytes als "Transaktion" packen kannst.

    Nicht nur schreiben, auch suchen geht auf 4 Bytes zusammengefasst (guck mal, wie strlen implementiert ist).

    Aber bedenke: All das, auch andere Optimierungen wie Fuellbytes, bringen uns weit weg von std::string als Datenstruktur fuer UTF-8.

    Ein std::string mit Füllbytes ist wie ein vector als priority_queue. Die Füllbyteoptimierung ist aber die gleiche wie für UTF-32.

    Und ja, vielleicht ist 2b2) mit dem String komplett kopieren 10% langsamer, weil malloc aufgerufen wird, aber da sind keine Welten zu UTF-32.



  • knivil schrieb:

    Natuerlich, wenn du deine Schreiboperation in einen Block aus 4 zusammenhaengenden Bytes als "Transaktion" packen kannst. Aber bedenke: All das, auch andere Optimierungen wie Fuellbytes, bringen uns weit weg von std::string als Datenstruktur fuer UTF-8.

    Bedenke: Selbst wenn ich nichts davon mache und einfach nur std::string verwende, passen mit UTF-8 ca. doppelt so viele Code Points in eine Cache Line. Wenn wir mit Vektorisierung anfangen, schauts für UTF-32 sowieso düster aus...



  • Nicht nur schreiben, auch suchen geht auf 4 Bytes zusammengefasst (guck mal, wie strlen implementiert ist).

    Ach, und ich dachte die Intel-Leute sind alles Narren mit ihrem MMX und SSE. Und zu strlen, es gibt Gruende warum es nicht auf mehreren Bytes arbeitet. Aber dazu muesste ich in der Tat nachsehen.

    Wenn wir mit Vektorisierung anfangen, schauts für UTF-32 sowieso düster aus

    Meine Erfahrung ist, dass variable Laenge echt scheisse ist, um mit SSE behandelt zu werden. Nun, die Erfahrung muss sich nicht auf UTF-8 uebertragen aber ich glaube kaum, dass UTF-8 mehr als alle anderen von Vektorisierung profitieren.

    Um mal die Diskussion zusammenzufasen: Ich sage A. Darauf folgt: Gaube A nicht. Das gilt auch anders herum.

    PS: Ich habe nachgesehen. Leider erzwingt die Implementation, dass das Ende von angefordertem Speicher genug Platz fuer 32/64-Bit bietet.



  • knivil schrieb:

    Entschuldigung, ich habe mich wohl falsch ausgedrueckt: UTF ist totaler Bockmist.

    +1


Anmelden zum Antworten