Dateigröße <<< Speicherverbrauch

Warum Debian und/oder eine seiner Spielarten? Was muss ich vorher wissen? Wo geht es nach der Installation weiter?
Antworten
kalamazoo
Beiträge: 301
Registriert: 28.08.2017 11:31:49

Dateigröße <<< Speicherverbrauch

Beitrag von kalamazoo » 23.09.2024 17:49:57

Verständnisfrage: wenn ich eine Datei mit 4,8 GB in Kate öffne, schwillt der RAM-Verbrauch von ca.3 GB auf über 30 GB an und das Swap-Memory von 0 auf knappe 7 GB. Warum ist dem so, warum benötigt eine nicht komprimierte einfache Textdatei im RAM ein vielfaches der eigenen Größe? Beim Schliessen der Datei wächst die Auslagerungsdatei noch zusätzlich auf über 16 GB an.
Weiters: solange ich Kate nicht beende, bleibt die RAM- bzw. Swap-Auslastung bei 30+ bzw 16+ GB .,..
Das Verhalten ist übrigens bei KWrite fast exakt dasselbe: gleiche Dateigrößen, Anstieg des Memoryverbrauchs beim Dateischliessen und Verbleiben im Speicher.

Edit: Typo ausgebessert!
Zuletzt geändert von kalamazoo am 23.09.2024 20:06:28, insgesamt 2-mal geändert.

rhHeini
Beiträge: 2706
Registriert: 20.04.2006 20:44:10

Re: Dateigröße <<< Speicherverbrauch

Beitrag von rhHeini » 23.09.2024 18:12:33

Frag mal bei KDE nach was die sich dabei gedacht haben.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 23.09.2024 18:26:45

Der individuelle Speicherverbrauch eines Programms kann sehr unterschiedlich sein. Da Kate zum Programmieren und fuer normalerweise recht kleine Textdateien gemacht ist, waren Ueberlegungen zum Speicherverbrauch dabei vermutlich Nebensache. Ob man fuer eine typische Quellcodedatei ein Mehrfaches der Dateigroesse an Speicher verbraucht ist normalerweise voellig egal, da der Grundspeicherbedarf der Anwendung einen viel groesseren Einfluss hat. Bei einer so grossen Datei wie du sie oeffnest ist das dann voellig anders.

Sicherlich koennte man viel weniger Speicher verbrauchen, dann wird man aber manche Dinge in der Anwendung anders programmieren muessen. Nehmen wir beispielsweise an, dass Kate irgendeine Listen-Datenstruktur aus der Qt/KDE-Standard-Library fuer die Verwaltung der Zeilen der Datei verwendet, dann braucht die halt so viel Speicher wie sie braucht. Wenn Kate weniger verbrauchen will, dann muesste sie dafuer eigenen Code schreiben. Das lohnt sich nur wenn der Anwendungsfall relevant genug ist.

Das macht den Sachverhalten vielleicht verstaendlich. Ich weiss nicht, warum tatsaechlich so viel Speicher verbraucht wird. Das Beschriebene koennten nur moegliche Erklaerungen sein.

Auch wenn ich den Speicherverbrauch in dem Fall massiv finde, verwundert er mich nicht allzu sehr. So ein Programm ist nicht die beste Option fuer so eine Datei. Andere Programme werden viel weniger Speicher brauchen. Probier's z.B. mal mit Vim aus ... nur als Vergleichswert. ;-) Sicherlich gibt es auch speichersparendere grafische Editoren.
Use ed once in a while!

kalamazoo
Beiträge: 301
Registriert: 28.08.2017 11:31:49

Re: Dateigröße <<< Speicherverbrauch

Beitrag von kalamazoo » 23.09.2024 21:30:54

Danke für die Erklärung, @Meillo, wird wohl so sein, aber eine fast 10-fache Größe erstaunt mich doch etwas ...

P.S. [diesmal an den Mod gerichtet]: aus irgendeinem unerfindlichen Grund scheint dieser Thread nicht unter "Eigene Beiträge" auf, sehr wohl aber unter "Neue Beiträge"; er wurde -- wie immer -- unter meinem Benutzernamen gepostet
"Kleiner-Als"-Zeichen im Titel? Bug?


EDIT: Benutzer kalamazoo spricht üblicherweise schwarz;
wenn er sich allerdings an die Mods wendet, dann spricht er rot
Zuletzt geändert von kalamazoo am 29.09.2024 15:36:09, insgesamt 1-mal geändert.

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 27.09.2024 03:45:21

Zuerst mal möchte ich anmerken, dass kate einer der wenigen Editoren ist, der überhaupt mit so großen Dateien klar kommt und sogar noch flüssig scrollen kann. Das ist leider noch immer keine Selbstverständlichkeit. Sonst finde ich den Faktor gar nicht so viel. Deine Datei wird vermutlich in UTF-8 sein. Das mach zwar Speicherplatzeffizienz ganz nett sein, aber das Decoding ist teuer. Intern nutzt QT UTF-16. Damit verdoppelst du schon mal den Speicherverbrauch. Dann willst du relativ flott zwischen Zeilen/Wörtern/Zeichen springen können. Klassisch haben Editoren das gelöst indem man einfach jede Zeile auf die Längste mit Platz gefüllt hat. Das ist denke ich vorbei. Trotzdem: Da gehört mindestens noch irgend ein Index dran. Das gilt noch viel mehr für Klammern, Zeilennummern, dynamische Umbrüche Zwischen denen man springen muss... Annotationen für was gehighlighted werden muss fürs syntaxhighlighting, welche Farbe was hat, Historie für Änderungen. Da hängt bestimmt an jedem 10. Buchstaben nochmal eine Metainformation, die sicher mehr als 10 Byte hat. Da sind wir schon Faktor 4. und so geht es vermutlich weiter.. Am besten mit doppeltem Buffer, damit man zurück springen kann falls irgend eine Aktion schief geht und schon ist man bei 8...
Und dann bist du noch immer bei einem Text-Only Modus. Wenn der fürs flüssige Scrollen alles im voraus rendert... Ein Buchstabe hat sicher 24x12 Pixel a RGB pro Byte bist du schon bei Faktor ~1000. Klar kate wird sicher nur die nähere Umgebung im Vorraus rendern. Aber eventuell auch noch in irgend einer Vektorrepräsentation, damit man zoomen kann...

kalamazoo
Beiträge: 301
Registriert: 28.08.2017 11:31:49

Re: Dateigröße <<< Speicherverbrauch

Beitrag von kalamazoo » 27.09.2024 04:21:07

Danke, @debra, für die detaillierte und erhellende Antwort! :THX: Dadurch ist mir einiges klarer geworden.
debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 03:45:21
Deine Datei wird vermutlich in UTF-8 sein.
Ja, UTF-8, aber reiner ASCII-Text (irgendeine hypertrophierte Logdatei).
debra hat geschrieben: ... welche Farbe was hat ..
Geht Farbe in Kate überhaupt???

... und ich dachte immer: Datei öffnen heisst in etwa von der Platte 1:1 in den RAM oder halt 1:1+ aufgrund irgendeines Overheads ...

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 27.09.2024 06:39:03

kalamazoo hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 04:21:07
... und ich dachte immer: Datei öffnen heisst in etwa von der Platte 1:1 in den RAM oder halt 1:1+ aufgrund irgendeines Overheads ...
Das kann man schon haben:

Code: Alles auswählen

:-Q ls -lk  /home/meillo/tmp/meillo.mbox
-rw------- 1 meillo meillo 340373 Sep 22  2012 /home/meillo/tmp/meillo.mbox

:-Q vim /home/meillo/tmp/meillo.mbox
[1] + Stopped              vim /home/meillo/tmp/meillo.mbox 

:-Q ps aux | egrep 'vim|USER'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
meillo   25817  1.4  4.6 421488 392444 pts/6   T    05:42   0:02 vim /home/meillo/tmp/meillo.mbox
meillo   26260  0.0  0.0  10176  1984 pts/2    S+   05:44   0:00 egrep vim|USER
Fuer die 340373k grosse Textdatei braucht Vim 392444k tatsaechlichen Speicher (RSS), das sind 52071k = 15% Overhead.


Es geht auch mit noch weniger:

Code: Alles auswählen

:-Q ed /home/meillo/tmp/meillo.mbox
348541308
^Z[2] + Stopped              ed /home/meillo/tmp/meillo.mbox 

:-Q ps aux | egrep 'ed /|USER'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
meillo   26510  8.8  0.5  97620 47548 pts/6    S+   05:48   0:03 ed /home/meillo/tmp/meillo.mbox
meillo   26531  0.0  0.0  10176  1984 pts/2    S+   05:48   0:00 egrep ed /|USER
Ed braucht nur 47548k Speicher! Also weniger Gesamtspeicher als Vim Overhead hat. Ed laedt die Datei also nicht komplett in den Speicher, sondern nur einen Index der Zeilen, damit er in der Datei schnell an die jeweilige Stelle kann.

Natuerlich ist ed auch nur ein Zeileneditor, aber prinzipiell koennten Vim oder Kate auch so aehnlich funktionieren: nur den aktuell angezeigten Teil der Datei laden ... bloss kann man dann halt kein globales Syntaxhighlighting und so Features haben und die Reaktionszeiten beim Scrollen und Springen in der Datei waeren langsamer. Luxusfeatures kosten nunmal Speicher ... und der Speicherverbrauch von Texteditoren ist selten fuer sehr grosse Dateien optimiert. Sie sind fuer das optimiert, fuer das sie zumeist eingesetzt werden.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 27.09.2024 07:00:36

Die Erlaeuterungen von debra zeigen schoen, was alles damit noch zusammenhaengt. :THX:

Diese Aussage sehe ich allerdings anders:
debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 03:45:21
Deine Datei wird vermutlich in UTF-8 sein. Das mach zwar Speicherplatzeffizienz ganz nett sein, aber das Decoding ist teuer.
Das Decoding von UTF-8 ist zwar etwas teurer als das von UTF-16, aber keinesfalls teuer. Man muss halt in jedes Zeichenanfangs-Byte reinschauen, wieviele Folgebytes es hat und man muss aus jedem gelesenen Byte die relevanten Bits rausholen (das erfordert verschiedene billige Bitoperationen). Sicherlich werden auch noch Validitaetschecks gemacht. Bei UTF-16 muss man zwar keine einzelnen Bits der Bytes extrahieren und neu kombinieren -- man spart sich also ein paar Bitoperationen -- aber man muss in die Bytes ebenfalls reinschauen und sie validieren, da es unerlaubte Bitfolgen gibt. So gross kann ich mir den Unterschied beim Decoding nicht vorstellen. Hast du dazu Zahlen?

Das Decoding ist eine reine Sache von (IMO vernachlaessigbarer) Rechenleistung und hat nichts mit dem Speicherverbrauch zu tun. Den Decoding-Unterschied koennte man im Zeitunterschied beim Oeffnen der Datei spueren. Jedoch werden dort andere Faktoren (wie die Qt-Bibliothek oder sonstige Initialisierungsarbeiten) vermutlich deutlich mehr Zeit brauchen und sich mehr von Programm zu Programm unterscheiden als die Unterschiede zwischen dem Dekodieren der unterschiedlichen Encodings. Darum meine ich, dass es vernachlaessigbar ist. Aber ich kenne dazu keine Messungen. Muesste das gleiche Programm mehrfach in einer Programmiersprache schreiben, die verschiedene Stringrepraesentationen unterstuetzt. Dann koennte man die Zeiten vergleichen.


Fuer den Speicherverbrauch ist relevant, welche Form der Stringkodierung die Programmiersprache, in der der Editor geschrieben ist, intern verwendet. Diese haben unterschiedlich viel Overhead. Ein ASCII-String in C hat 1 Byte Overhead pro Zeile. Ein ASCII-String in modernen Scriptsprachen, die meist UTF-16-Strings haben, hat zweimal die Anzahl der Zeichen plus einen Integer fuer die Laenge an Overhead pro Zeile. Der Speicherverbrauch zwischen einem C-Programm und einem Programm mit intern UTF-16-Strings verdoppelt sich also gleich schon mal ... insofern die Textdatei fast nur aus US-ASCII-Zeichen besteht. Bei griechischem Text beispielsweise sieht das aber gleich anders aus.
Use ed once in a while!

kreuzschnabel
Beiträge: 498
Registriert: 24.09.2020 14:51:14

Re: Dateigröße <<< Speicherverbrauch

Beitrag von kreuzschnabel » 27.09.2024 07:08:14

kalamazoo hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 04:21:07
debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 03:45:21
... welche Farbe was hat ..
Geht Farbe in Kate überhaupt???
Im Text nicht, aber in der Darstellung – die Rede war von Syntaxhighlighting :)

--ks
Hier so: Debian Stable/Sid (nach Laune) – KDE Plasma – Lenovo Thinkpad T470p – i7-7700HQ – 32GB RAM

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 27.09.2024 08:23:12

kalamazoo hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 04:21:07
Ja, UTF-8, aber reiner ASCII-Text (irgendeine hypertrophierte Logdatei).
Ja bei allem außer ASCII ist UTF-16 ja platz effizienter als UTF-8. Du hast also das absolute worst case Szenario Ein „ (unteres Anführungszeichen) hat in UTF-8 drei Byte in UTF-16 nur zwei.
Geht Farbe in Kate überhaupt???
Klar hebt dir den Platz zwischen Klammern hervor, unterstreicht dir falsch geschriebene Wörter...
Datei öffnen heisst in etwa von der Platte 1:1 in den RAM oder halt 1:1+ aufgrund irgendeines Overheads ...
Und ich habe dir geschrieben, warum man das nicht macht.
So gross kann ich mir den Unterschied beim Decoding nicht vorstellen. Hast du dazu Zahlen?

Code: Alles auswählen

time cat enwik9-16 | time uconv -f utf-16 -t utf-16 -x '::nfkc; [:Cc:] >; ::katakana-hiragana;'
time cat enwik9 | time uconv -f utf-8 -t utf-8 -x '::nfkc; [:Cc:] >; ::katakana-hiragana;'
Macht bei mir 13% Unterschied. Ist also wirklich ziemlich vernachlässigbar. Das ist aber nur englischer Text und damit quasi nur ASCII und vor allem halt eine komplexe Operation. Relevant für kate dürfte eher Zeichen und Zeilen zählen sein. Leider kenne ich kein Tool das das auf die Schnelle macht. wc kann nur ASCII und UTF-8. Da sind die Unterschiede aber erheblich:

Code: Alles auswählen

LANG=C.UTF-8 wc -m enwik9-ASCII
braucht über 2s

Code: Alles auswählen

LANG=C wc -m enwik9-ASCII
unter einer ms.

Code: Alles auswählen

Muesste das gleiche Programm mehrfach in einer Programmiersprache schreiben, die verschiedene Stringrepraesentationen unterstuetzt.
qstring in qt4 konnte das noch. In qt5 ist das raus geflogen. UTF-8 im Konstruktor aber UTF-16 als interne Kodierung. Angeblich ist UTF-16 in quasi allen Fällen nahe an der beste Wahl.
Ein ASCII-String in C hat 1 Byte Overhead pro Zeile.
Aber es gibt keinen Editor mehr, der nur ASCII kann. Dann musst du mindestens wchars nehmen und dann bist du auch wieder bei UTF-16 oder irgend was ähnlichem...

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 27.09.2024 09:11:27

debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 08:23:12
kalamazoo hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 04:21:07
Ja, UTF-8, aber reiner ASCII-Text (irgendeine hypertrophierte Logdatei).
Ja bei allem außer ASCII ist UTF-16 ja platz effizienter als UTF-8. Du hast also das absolute worst case Szenario Ein „ (unteres Anführungszeichen) hat in UTF-8 drei Byte in UTF-16 nur zwei.
Man muss hier genau hinschauen, was jeweils gemeint ist. Bei reinem US-ASCII braucht UTF-8 jeweils ein Byte, UTF-16 jeweils zwei Bytes. Bei deutschem Text (mit Umlauten und ß) braucht UTF-8 fuer die allermeisten Zeichen (die in US-ASCII enthalten sind) ein Byte und fuer ein paar Zeichen zwei Bytes. UTF-16 braucht immer zwei Bytes. UTF-8 braucht immer weniger Platz als UTF-16, ausser es enthaelt mehr 3-Byte-Zeichen als US-ASCII-Zeichen. Bei westeuropaeischen Texten ist das eigentlich nie der Fall. Das wirkt sich bei asiatischen Texten aus. In den anderen -- und so gut wie allen fuer Deutschsprachige relevanten -- Texten ist UTF-8 speichereffizienter als UTF-16.
debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 08:23:12
So gross kann ich mir den Unterschied beim Decoding nicht vorstellen. Hast du dazu Zahlen?

Code: Alles auswählen

time cat enwik9-16 | time uconv -f utf-16 -t utf-16 -x '::nfkc; [:Cc:] >; ::katakana-hiragana;'
time cat enwik9 | time uconv -f utf-8 -t utf-8 -x '::nfkc; [:Cc:] >; ::katakana-hiragana;'
Macht bei mir 13% Unterschied. Ist also wirklich ziemlich vernachlässigbar. Das ist aber nur englischer Text und damit quasi nur ASCII und vor allem halt eine komplexe Operation. Relevant für kate dürfte eher Zeichen und Zeilen zählen sein. Leider kenne ich kein Tool das das auf die Schnelle macht. wc kann nur ASCII und UTF-8. Da sind die Unterschiede aber erheblich:

Code: Alles auswählen

LANG=C.UTF-8 wc -m enwik9-ASCII
braucht über 2s

Code: Alles auswählen

LANG=C wc -m enwik9-ASCII
unter einer ms.
Das stimmt. Bei US-ASCII muessen nur die Bytes gezaehlt werden. D.h. man kann auch jeweils 4096 Bytes auf einmal laden und den Counter um soviel erhoehen. Man muss noch nicht mal einzelne Bytes anschauen. Insofern man auf die Validitaetspruefung beim Lesen von UTF-16 verzichtet, koennte man das auch so machen. Aber ich vermute, dass UTF-16-Implementierungen die Bytes schon anschauen, ob sie valide sind. Dann muss man da jeweils zwei Bytes lesen, pruefen und zaehlen. Bei UTF-8 gibt das Start-Byte eines Zeichens an, wieviele Folgebytes es hat. D.h. man muss in das erste Byte eines Zeichen reinschauen. Die Folgebytes koennte man dann ueberspringen, oder eben validieren.

Aber du hast schon Recht, wenn man sich in einem UTF-8-String bewegt, dann man muss die Zeichen jeweils dekodieren, um zeichenweise navigieren zu koennen. Bei UTF-16 ... und allen Festbreitenkodierungen kann man direkt mit Vielfachen der Festbreite arbeiten. Wie fast immer hat alles Vor- und Nachteile und man muss sich entscheiden, welche Prioritaeten man hat.


Btw: Weiss zufaellig jemand, wie Runes in Go intern umgesetzt sind? Dort gibt es kein UTF-16 (weil die Erfinder von UTF-8 natuerlich wissen, dass es einfach besser ist als das schreckliche UTF-16 :-P :-D ) aber wie setzt man UTF-8-Strings intern um ohne viel Speicher zu verbrauchen?
Use ed once in a while!

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 27.09.2024 13:05:04

UTF-16 jeweils zwei Bytes.
Nicht unbedingt Hieroglyphen und Smilies haben auch mal 4. Aber du hast halt einen Check ob das erste Bit 0 ist und kannst mehr oder weniger garantieren, dass der in 99.99% nicht genommen wird. Entsprechend werden da auch passende Sprungvorhersagen etc. gut funktionieren.
Das stimmt. Bei US-ASCII muessen nur die Bytes gezaehlt werden
Ok. wc scheint das wirklich so dumm zu machen.
Deswegen etwas fairer:

Code: Alles auswählen

LANG=C time wc -w enwik9-ASCII
LANG=C.UTF-8 time wc -w enwik9-ASCII 
Und dann ist die UTF-8 Variante zuverlässig ~30% schneller. Warum?!
Die Folgebytes koennte man dann ueberspringen, oder eben validieren.
Da das Programm das Byte ja selber schreibt, braucht man das eher nicht validieren. Aber du hast halt bei UTF-8 quasi immer 4 verschiedene Varianten für die du dann noch für alles, was nicht ASCII ist, Bits masken und shiften musst. Bei UTF-16 ist das quasi ausschließlich für Smilies der Fall. Sonst hast du direkt dein Unicode. Selbst alle Zeichen auf sina.com.cn liegen noch im 2-Byte Bereich von UTF-16 nur Obskuritäten wie die Dame🨁sind komplexer. Da kannst du dir fast schon Annotation an deine Strings machen, ob die noch UCS-2 sind, und die wichtigsten Funktionen doppelt implementieren.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 27.09.2024 13:57:02

debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 13:05:04

Code: Alles auswählen

LANG=C time wc -w enwik9-ASCII
LANG=C.UTF-8 time wc -w enwik9-ASCII 
Und dann ist die UTF-8 Variante zuverlässig ~30% schneller. Warum?!
Kann ich mir nicht erklaeren. Aus meiner Sicht sollten beide Varianten gleich schnell sein, da Whitespace in beiden Faellen identisch definiert sein sollte: Entweder nur bestimmte Zeichen aus US-ASCII oder ggf. abhaengig vom Locale. US-ASCII-Zeichen sehen in US-ASCII-Text gleich aus wie in UTF-8-Text.
Manpage wc(1) hat geschrieben: A word is a non-zero-length sequence of characters delimited by white space.
debra hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 13:05:04
Bei UTF-16 ist das quasi ausschließlich für Smilies der Fall. Sonst hast du direkt dein Unicode. Selbst alle Zeichen auf sina.com.cn liegen noch im 2-Byte Bereich von UTF-16 nur Obskuritäten wie die Dame🨁sind komplexer. Da kannst du dir fast schon Annotation an deine Strings machen, ob die noch UCS-2 sind, und die wichtigsten Funktionen doppelt implementieren.
What?! 8O Dann hat man ja das Schlechte aus beiden Welten. :facepalm: Das macht doch konzeptionell gar keinen Sinn. UTF-16 ist nur dann sinnvoll, wenn es ein Festbreitenencoding ist und das erzwingt, dass es nur eine begrenzte Menge an Zeichen abbilden kann. Welche Menge das ist, ist ein Kompromis zwischen Menge der Zeichen und Speicherverbrauch. Wenn man das durch eine doch variable Zeichenlaenge aufbricht, dann kann man doch gleich UTF-8 nehmen, welches so gut wie immer weniger Speicher braucht, technisch 31-Bit fuer die Zeichenkodierung genutzt werden koennen, und es vor allem keine schrecklichen Byte-Order-Probleme gibt, plus weitere Vorteile wie erkennen zu koennen, ob man sich am Anfang oder in der Mitte eines Mehrbytezeichens befindet. Wenn UTF-16 kein Festbreitenencoding mehr ist, dann verliert es seinen einzigen Vorteil.

Du siehst, ich bin ein entschiedener Gegner von UTF-16. Es ist zwar auf den ersten Blick einfach und pragmatisch, auf den genaueren Blick aber in vielerlei Weise problematisch.



(Nachtrag: Mir war gar nicht bewusst, dass UTF-16 kein Festbreitenencoding ist. Mit diesem Wissen finde ich es noch viel schlechter als zuvor. Ich sehe keinen einzigen Grund, warum UTF-16 sinnvoll sein soll. In den meisten Faellen ist UTF-8 besser und in ein paar Faellen ist UTF-32 besser, aber UTF-16 ist nie das beste Verfahren.)
Zuletzt geändert von Meillo am 28.09.2024 07:31:26, insgesamt 1-mal geändert.
Grund: Nachtrag
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 28.09.2024 07:12:39

Meillo hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 09:11:27
Btw: Weiss zufaellig jemand, wie Runes in Go intern umgesetzt sind?
Dazu habe ich nun nachgelesen:
https://go.dev/blog/strings hat geschrieben: In Go, a string is in effect a read-only slice of bytes.

[...]

As implied up front, indexing a string accesses individual bytes, not characters.

[...]

The Go language defines the word rune as an alias for the type int32 [...]

[...]

Besides the axiomatic detail that Go source code is UTF-8, there’s really only one way that Go treats UTF-8 specially, and that is when using a for range loop on a string.

We’ve seen what happens with a regular for loop. A for range loop, by contrast, decodes one UTF-8-encoded rune on each iteration. Each time around the loop, the index of the loop is the starting position of the current rune, measured in bytes, and the code point is its value. Here’s an example using yet another handy Printf format, %#U, which shows the code point’s Unicode value and its printed representation:

const nihongo = "日本語"
for index, runeValue := range nihongo {
fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
}

The output shows how each code point occupies multiple bytes:

U+65E5 '日' starts at byte position 0
U+672C '本' starts at byte position 3
U+8A9E '語' starts at byte position 6
Man kann sich in Go also aussuchen, ob man mit den Bytes des Strings arbeiten will oder mit den (dekodierten) Zeichen (Runes).

Runes sind 4 Bytes lang (also wie in einem UTF-32-Encoding). Es ist optional in Go, einen String in ein Slice (=Array) von Runes zu konvertieren, ebenso gut kann man on-the-fly das UTF-8 dekodieren oder direkt auf den Bytes arbeiten.

Was das fuer das einen Texteditor in Go bedeutet, ist eine interessante Frage. Es wird wie immer sein: man kann Speicherverbrauch gegen Rechenzeit tauschen und umgekehrt, je nachdem was einem im jeweiligen Fall wichtiger ist.
Use ed once in a while!

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 28.09.2024 17:53:48

wenn es ein Festbreitenencoding ist und das erzwingt, dass es nur eine begrenzte Menge an Zeichen abbilden kann. Welche Menge das ist, ist ein Kompromis zwischen Menge der Zeichen und Speicherverbrauch.
Perl macht das glaube ich sogar mit 1-Byte. Jeder String bekommt ein custom-encoding in dem alle Zeichen drin sind. Gibt es mehr als 255 unterschiedliche wird der String intern geteilt. Zumindest abseits von China rasend schnell aber ein Pain das verständlich zu implementieren.
Wenn man das durch eine doch variable Zeichenlaenge aufbricht, dann kann man doch gleich UTF-8 nehmen
Auf der überwältigenden Mehrheit der Systeme sind int32 Operationen deutlich schneller als Byte Operationen. Die willst du nutzen. Du musst also sowieso bitbanging machen. Bei UTF-16 fallen die Buchstabengrenzen halt fast immer auf int32 Grenzen. Es kann einen super speziellen Fall geben. Aber der kommt halt fast nie vor. Der Test darauf ist sehr billig und die Sprungvorhersage optimiert dir alles andere raus. Bei UTF-8 ist der Test wie lange ein Zeichen ist, deutlich teurer und der Fall dass ein Zeichen über ein int hinaus läuft alles andere als ein absoluter Edge Case.
und es vor allem keine schrecklichen Byte-Order-Probleme gibt, plus weitere Vorteile wie erkennen zu koennen, ob man sich am Anfang oder in der Mitte eines Mehrbytezeichens befindet.
Alles Sachen, die relevant für ein Dateiformat/Austauschencoding sind. Deswegen will QT und Go nur noch UTF-8-Strings im Source. Für deine interne Repräsentation ist dir das vollständig Wurst: Du schreibst die Strings selbst. In der Byte-Order die du gewählt hast und in dem Alighnment, dass du für richtig hältst. In Hardware wird intern vermutlich eh in 32Bit Blöcken oder größer gearbeitet... Da musst du dir ganz andere Gedanken machen.
da Whitespace in beiden Faellen identisch definiert sein sollte: Entweder nur bestimmte Zeichen aus US-ASCII oder ggf. abhaengig vom Locale. US-ASCII-Zeichen sehen in US-ASCII-Text gleich aus wie in UTF-8-Text.
Achtung Wörter können nicht nur durch Leerzeichen getrennt sein, sondern auch durch / oder Punkt und Zeilenumbruch... Das Problem ist eine Nummer komplexer. In UTF-8 ist die Auswahl deutlich größer als in ASCII. Man sollte also annehmen, dass der Abgleich deutlich länger geht. Das Programm weiß ja nicht, dass im Text nur ASCII vorkommt und muss deswegen auch gegen – und nicht nur gegen - abgleichen – Auch wenn das in der Realität nie vorkommt.
Es wird wie immer sein: man kann Speicherverbrauch gegen Rechenzeit tauschen und umgekehrt, je nachdem was einem im jeweiligen Fall wichtiger ist.
Real ist das extrem selten der Fall. Auch wenn deine 32Bit-Zeichen wunderbar zu deinen 32Bit Operationen passen und so relativ naheliegend performante Implementierungen ergeben. SIMD ist ein Ding und wird bei Stringverarbeitung massiv eingesetzt. Da bekommst du halt nur halb so viele Zeichen pro Tankt verarbeitet. Deine Register haben eine bestimmte Größe. Genau so dein Cache und dein RAM und deine RAM Zeilen... Mehr Daten führt quasi immer zu langsameren Verarbeitungszeiten. Deine UCS-4-Runes werden vermutlich überall abseits von Sprüngen mit fester Buchstabenlänge über sehr viele Zeichen beschissen performen. Oft ist das komplexere Programm eben doch das schnellere: UTF-16 bietet halt in den aller meisten Fällen eine genau so primitive Implementierung wie UCS-4 wird aber wegen den Operationen auf deutlich kleineren Datenmengen deutlich schneller sein. Es benötigt immer einen hässlich komplexen Special-Case, der aber einfach erkannt werden kann und so gut wie nie vorkommt. – So ändert er fast nichts an der durchschnittlichen Laufzeit. Das hast du halt bei UTF-8 nicht mehr: Prüfst du stumpf auf erstes Bit 1 kommt das doch recht regelmäßig vor und die Behandlung danach wird ungleich komplexer.

kalamazoo
Beiträge: 301
Registriert: 28.08.2017 11:31:49

Re: Dateigröße <<< Speicherverbrauch

Beitrag von kalamazoo » 29.09.2024 15:43:17

Nachdem dieser Faden bei mir nicht unter "Eigene Beiträge" aufscheint, ist er ein wenig dem Blickfeld entschwunden -- ich könnte aber auf dem derzeitigen Niveau ohnedies nichts wirklich Sinnvolles beitragen. Chapeau @debra und @Meillo! :THX:
kreuzschnabel hat geschrieben: ↑ zum Beitrag ↑
27.09.2024 07:08:14
Im Text nicht, aber in der Darstellung – die Rede war von Syntaxhighlighting :)
Danke, bin gerade vom Schlauch heruntergestiegen :facepalm:

P.S. (weil es so iiiiiiirgendwieee dazupasst): ich habe mittlerweile mein altes Problem mit der Zeichendarstellung in KDE-Plasma lösen können (viewtopic.php?p=1371860); die Lösung ist simpel, ... wenn man weiss wie es geht

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 01.10.2024 08:40:04

debra hat geschrieben: ↑ zum Beitrag ↑
28.09.2024 17:53:48
wenn es ein Festbreitenencoding ist und das erzwingt, dass es nur eine begrenzte Menge an Zeichen abbilden kann. Welche Menge das ist, ist ein Kompromis zwischen Menge der Zeichen und Speicherverbrauch.
Perl macht das glaube ich sogar mit 1-Byte. Jeder String bekommt ein custom-encoding in dem alle Zeichen drin sind. Gibt es mehr als 255 unterschiedliche wird der String intern geteilt. Zumindest abseits von China rasend schnell aber ein Pain das verständlich zu implementieren.
In diese Richtung habe ich auch noch ein bisschen gedacht, als du zuvor schon erwaehnt hast, dass man in der Sprache unterschiedliche Strings unterschiedlich encoden kann. Beim Beispiel Texteditor koennte man folglich jede Zeile mit einem anderen Festbreitenencoding ablegen. Also wenn sie nur US-ASCII-Zeichen enthaelt, dann nehmen wir ein Byte pro Zeichen, wenn mehr noetig ist, dann fuer die BMP sowas wie UTF-16 (aber ohne die Erweiterung mit variabler Zeichenlaenge), und fuer den Rest UTF-32. Der Editor haette dann einen recht kleinen Speicherverbrauch, koennte immer mit Festbreitenencodings arbeiten, und muesste nur hin und wieder eine Zeile umcodieren. Das Umcodieren waere in dem Fall aber nicht so schlimm, weil man beim ``Hochkodieren'' einfach nur Null-Bytes einfuegen muesste, die man beim ``Runterkodieren'' die Zusatzbytes einfach entfernen kann, wenn sie im ganzen String alle null sind. Das waere eine nette Programmieraufgabe, das mal auszuprobieren, ob das so machbar waere. ;-) (Schade, dass ich kein Student mit viel Zeit mehr bin.)
debra hat geschrieben: ↑ zum Beitrag ↑
28.09.2024 17:53:48
Du musst also sowieso bitbanging machen. Bei UTF-16 fallen die Buchstabengrenzen halt fast immer auf int32 Grenzen. Es kann einen super speziellen Fall geben. Aber der kommt halt fast nie vor. Der Test darauf ist sehr billig und die Sprungvorhersage optimiert dir alles andere raus. Bei UTF-8 ist der Test wie lange ein Zeichen ist, deutlich teurer und der Fall dass ein Zeichen über ein int hinaus läuft alles andere als ein absoluter Edge Case.
Das mit den int-Grenzen ueberzeugt mich.

Was mich nicht ueberzeugt ist, dass der Test bei UTF-8 deutlich teurer waere. Natuerlich muss man da in jedes Byte reinschauen, aber bei UTF-16 muss man das auch! Dass die ``erweiterten'' Zeichen bei UTF-16 nur sehr selten vorkommen, aendert nichts am Aufwand, denn jedes Zeichen koennte ein solches erweitertes Zeichen sein, auch wenn es dann tatsaechlich so gut wie nie der Fall ist. Den Aufwand, bei jedem Zeichen trotzdem reinschauen zu muessen, reduziert sich dadurch nicht. Das waere anders wenn UTF-16 tatsaechlich ein Festbreitenencoding waere. Somit ist aus meiner Sicht der Aufwand in beiden Faellen vergleichbar. Aber fuehre gerne nochmal aus, was genau bei UTF-8 diesbezueglich teurer sein soll als bei UTF-16.
debra hat geschrieben: ↑ zum Beitrag ↑
28.09.2024 17:53:48
und es vor allem keine schrecklichen Byte-Order-Probleme gibt, plus weitere Vorteile wie erkennen zu koennen, ob man sich am Anfang oder in der Mitte eines Mehrbytezeichens befindet.
Alles Sachen, die relevant für ein Dateiformat/Austauschencoding sind. Deswegen will QT und Go nur noch UTF-8-Strings im Source. Für deine interne Repräsentation ist dir das vollständig Wurst: Du schreibst die Strings selbst. In der Byte-Order die du gewählt hast und in dem Alighnment, dass du für richtig hältst.
Zustimmung.
debra hat geschrieben: ↑ zum Beitrag ↑
28.09.2024 17:53:48
da Whitespace in beiden Faellen identisch definiert sein sollte: Entweder nur bestimmte Zeichen aus US-ASCII oder ggf. abhaengig vom Locale. US-ASCII-Zeichen sehen in US-ASCII-Text gleich aus wie in UTF-8-Text.
Achtung Wörter können nicht nur durch Leerzeichen getrennt sein, sondern auch durch / oder Punkt und Zeilenumbruch...
Im Falle von wc(1) ist definiert, dass nur Whitespace Woerter trennt:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/wc.html hat geschrieben: The wc utility shall consider a word to be a non-zero-length string of characters delimited by white space.

[...]

LC_CTYPE
Determine the locale for the interpretation of sequences of bytes of text data as characters (for example, single-byte as opposed to multi-byte characters in arguments and input files) and which characters are defined as white-space characters.

[...]

Some historical implementations use only <space>, <tab>, and <newline> as word separators. The equivalent of the ISO C standard isspace() function is more appropriate.
debra hat geschrieben: ↑ zum Beitrag ↑
28.09.2024 17:53:48
Es wird wie immer sein: man kann Speicherverbrauch gegen Rechenzeit tauschen und umgekehrt, je nachdem was einem im jeweiligen Fall wichtiger ist.
Real ist das extrem selten der Fall. Auch wenn deine 32Bit-Zeichen wunderbar zu deinen 32Bit Operationen passen und so relativ naheliegend performante Implementierungen ergeben. SIMD ist ein Ding und wird bei Stringverarbeitung massiv eingesetzt. Da bekommst du halt nur halb so viele Zeichen pro Tankt verarbeitet. Deine Register haben eine bestimmte Größe. Genau so dein Cache und dein RAM und deine RAM Zeilen... Mehr Daten führt quasi immer zu langsameren Verarbeitungszeiten. Deine UCS-4-Runes werden vermutlich überall abseits von Sprüngen mit fester Buchstabenlänge über sehr viele Zeichen beschissen performen. Oft ist das komplexere Programm eben doch das schnellere: UTF-16 bietet halt in den aller meisten Fällen eine genau so primitive Implementierung wie UCS-4 wird aber wegen den Operationen auf deutlich kleineren Datenmengen deutlich schneller sein. Es benötigt immer einen hässlich komplexen Special-Case, der aber einfach erkannt werden kann und so gut wie nie vorkommt. – So ändert er fast nichts an der durchschnittlichen Laufzeit. Das hast du halt bei UTF-8 nicht mehr: Prüfst du stumpf auf erstes Bit 1 kommt das doch recht regelmäßig vor und die Behandlung danach wird ungleich komplexer.
Du schreibst, dass weniger Daten schneller verarbeitet werden wuerden als mehr Daten (2 Bytes schneller als 4 Bytes), zugleich schreibst du, dass mehr Daten schneller verarbeitet werden wuerde als weniger (2 Bytes schneller als 1 Byte). Das verstehe ich nicht recht.

UTF-8-Text, der typischerweise in Editoren verarbeitet wird, besteht in UTF-8 sicherlich zu mehr als 90% aus 1-Byte-Zeichen und dann noch ein paar 2-Byte-Zeichen. 3- und 4-Byte-Zeichen sind in UTF-8 wahrscheinlich aehnlich selten wie die erweitereten 4-Byte-Zeichen in UTF-16.

Ich verstehe nicht recht, warum du der Meinung bist, dass Computer 16-Bit-Einheiten schneller verarbeiten koennten als sowohl 8-Bit- als auch 32-Bit-Einheiten. Was ist so magisch an den 16-Bits?

Was ich verstehe ist der Alignment-Aspekt, der mit UTF-16 meist und mit UTF-32 immer erreicht wird, mit UTF-8 aber etwas weniger oft (jedoch immer noch oft, da rund 90% der Zeichen 1-Byte-Zeichen sein werden, die immer alignen).

Ich werde in den naechsten Tagen ein kleines Programm schreiben, das Textdateien analysiert, wieviele Multi-Byte-Zeichen sie enthalten und inwiefern sie alignen, um dafuer mal Zahlen aus der Praxis zu bekommen. Falls jemand dazu bereits gemachte Auswertungen kennt, bitte verlinken.
Zuletzt geändert von Meillo am 01.10.2024 10:25:32, insgesamt 1-mal geändert.
Grund: Kleine Anpassung
Use ed once in a while!

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 01.10.2024 23:50:29

Meillo hat geschrieben: ↑ zum Beitrag ↑
01.10.2024 08:40:04
Natuerlich muss man da in jedes Byte reinschauen, aber bei UTF-16 muss man das auch!
Der Test ist nur viel einfacher: !(char^0x8000) ist ein sehr einfacher Test der dir direkt die zwei möglichen Varianten generiert: Nachfolgendes int32 muss mit einem einzelnen rotieren der vorderen 16Bits und nem Tausch der beiden int16 decoded werden. (Zwei Operationen.) Oder kann als int16 kann direkt verwendet werden. Ein !(char^0x80008000) cleared dich direkt für die beiden Zeichen.
!(char^0x80) sagt dir erst mal noch wenig: Klar wenn es gut geht ist es ASCII. Aber sonst: wird es sehr komplex. Und wie gesagt: Das ist um Größenordnungen häufiger. Wenn du 90% ASCII hast, dann hast du in 18% der Fälle einen anderen Fall, als im vorherigen Durchlauf. Bei UTF-16 kannst du selbst bei chinesischen Texten davon ausgehen, dass du eher bei 99.999% der Fälle bist. Multiplizierst du das mit der Wahrscheinlichkeit, dass zwei Zeichen auf einmal UTF-8 sind bist du bei 33% Fehlschalgsrate. 90% ASCII ist natürlich hart untertrieben. Aber wenn du bedenkst dass eine fehlgeschlagene Sprungvorhersage gerne mal ein zwanzigfaches kostet, wird das böse, wenn nur wenige Prozent fehl schlagen.
Dass die ``erweiterten'' Zeichen bei UTF-16 nur sehr selten vorkommen, aendert nichts am Aufwand, denn jedes Zeichen koennte
Deswegen haben wir spekulative Ausführung. Der Rechner nimmt erst mal an, dass es nicht der Fall ist, und macht dann extrem teuer eine Rolle rückwärts, wenn es doch der Fall ist.
Das waere anders wenn UTF-16 tatsaechlich ein Festbreitenencoding waere. Somit ist aus meiner Sicht der Aufwand in beiden Faellen vergleichbar. Aber fuehre gerne nochmal aus, was genau bei UTF-8 diesbezueglich teurer sein soll als bei UTF-16.
Man kann sie oft so behandeln: Zwei aufeinander folgende Bytes die mit 0 anfangen sind sicher exakt ein Zeichen. Zwei aufeinander folgende Bytes, die mit 0 anfangen sind in UTF-8 eben mal 2 Zeichen mal 1.5 mal 1⅓.…. Ein einzelnes Byte, dass mit null anfängt, ist mal ein Zeichen, mal 1.5, mal...
debra hat geschrieben: ↑ zum Beitrag ↑
28.09.2024 17:53:48
Du schreibst, dass weniger Daten schneller verarbeitet werden wuerden als mehr Daten (2 Bytes schneller als 4 Bytes), zugleich schreibst du, dass mehr Daten schneller verarbeitet werden wuerde als weniger (2 Bytes schneller als 1 Byte). Das verstehe ich nicht recht.
Grundsätzlich: Mehr Daten ist meistens langsamer: Mehr Code auch. Im Vergleich zu UCS-4 hat UTF-16 halb so viel Daten und minimal mehr Code, der real ausgeführt wird. Das ist kein fair Match. UTF-8 hat im Vergleich zu UTF-16 auch halb so viel Daten aber halt deutlich mehr Code.
3- und 4-Byte-Zeichen sind in UTF-8 wahrscheinlich aehnlich selten wie die erweitereten 4-Byte-Zeichen in UTF-16.
Nein. Alle Smilies, quasi alle chinesischen Zeichen, die meiste Punktuation ist 3-Byte aber in UTF-16 nur 2. Es gibt kein Unicode Zeichen dass in das in UTF-16 4 Byte braucht aber in UTF-8 nur 3, da hinter den Chinesischen Zeichen ein Loch gelassen wurde, dass dann für die Erweiterungen nicht gereicht hat. Reiner deutsche Fließtext dürfte etwas anders aussehen. Ist aber sicher nicht repräsentativ.
Ich verstehe nicht recht, warum du der Meinung bist, dass Computer 16-Bit-Einheiten schneller verarbeiten koennten als sowohl 8-Bit- als auch 32-Bit-Einheiten. Was ist so magisch an den 16-Bits?
Weil die Prozesor Hersteller machen halt Statistiken machen, was am häufigsten genutzt wird. Da ist 32 halt ganz vorne und dann 64 und 16Bit. Byte Operationen nicht. Entsprechend optimieren sie ihre Prozessoren, dass die Operationen in einem Takt durch laufen. Passend macht das gcc mit -march=znver3 -O3 bei mir aus

Code: Alles auswählen

  volatile int64_t c=12;
  uint8_t b=c;
  uint8_t a=7;
  a+=b;
  a*=b;
Dasda:

Code: Alles auswählen

lea    0x7(%rdx),%eax
imul   %edx,%eax
movzbl %al,%eax
Der rechnet hier sogar wenn man ihm 64Bit gibt und 64Bit haben will die 8Bit-Operationen auf 32Bit um dann mit Nullen zu füllen. Das ist natürlich ein selbstverstärkender Effekt.Weil die Prozessorhersteller das machen, machen das die Compiler, weswegen das die Prozessorhersteller noch mehr machen...
Wenn du jetzt performanten UTF-16 Code schreiben willst, verarbeitet der immer 2 16Bit-Zeichen auf einmal. Was quasi immer funktioniert. Performanter UTF-8 Code versucht vermutlich 4 8Bit-Zeichen zu nehmen. Das funktioniert dann bei weitem nicht mehr so oft: Bei 90% ASCII und je 5% 2Byte und 3Byte UTF-8 bist du nur noch bei 56%, dass das gut geht. => Deine Sprungerkennung geht relativ häufig kaputt...

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 03.10.2024 22:07:55

Zuerstmal habe ich den vorherigen Beitrag lesbar gemacht. Sonst habe ich mal eine Statistiken zu den Namen, die in der Weltkarte von Osmand auftauchen. (Ich habe vorher uniq drüber laufen lassen, weil viele Flüsse etc in viele gleichnamige Teile aufgeteilt sind.)
Insgesamt 21717221 Zeichen.
Davon

Code: Alles auswählen

17957426 ( 83%) ASCII
 2616854 ( 12%) 2-Byte UTF-8
 1142629 (  5%) 3-byte UTF-8
     312 (.01‰) 4-Byte UTF-8
     313 (.01‰) 4-byte UTF-16
21716908 (100%) 2-Byte UTF-16
 5682050 ( 26%) H, die ich als Trennzeichen verwendet habe
Es scheint also doch Zeichen zu geben, die 3-Byte in UTF-8 haben und 4 in UTF-16. Eventuell ist da aber auch schlicht ein fehlerhaft codiertes Zeichen im Datensatz.
Klar das ist Natürlich ein bisschen fies, weil anteilig viel mehr Texte in englisch/Programmiersprachen... geschrieben sind als Straßennahmen. Aber auch wenn die Weltübersicht das vermutlich weitestgehend Nivelliert, dürfte Europa+Russland und Amerika weit überrepräsentiert sein, die alle in erster Linie 2-Byte encodings nutzen. Während in Afrika, Naher Osten und Asien inklusive allen drei CYK-länder fast keine Änderungen pro Einwohner haben.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 14.10.2024 17:12:06

So, endlich antworte ich hier.

debra hat geschrieben: ↑ zum Beitrag ↑
01.10.2024 23:50:29
Meillo hat geschrieben: ↑ zum Beitrag ↑
01.10.2024 08:40:04
Natuerlich muss man da in jedes Byte reinschauen, aber bei UTF-16 muss man das auch!
Der Test ist nur viel einfacher: !(char^0x8000) ist ein sehr einfacher Test der dir direkt die zwei möglichen Varianten generiert: Nachfolgendes int32 muss mit einem einzelnen rotieren der vorderen 16Bits und nem Tausch der beiden int16 decoded werden. (Zwei Operationen.) Oder kann als int16 kann direkt verwendet werden. Ein !(char^0x80008000) cleared dich direkt für die beiden Zeichen.
!(char^0x80) sagt dir erst mal noch wenig: Klar wenn es gut geht ist es ASCII. Aber sonst: wird es sehr komplex. Und wie gesagt: Das ist um Größenordnungen häufiger.
Das ``sehr komplex'' sind auch nur Bitoperationen, zusaetzlich zum obigen noch Shifts. Das wuerde ich nicht komplexer nennen, aber ich stimme zu, dass es der Prozess insgesamt aufaendiger ist. Vielleicht geht es dir auch vor allem um die Fallunterscheidungen, die oefters vorkommen als bei UTF-16.
debra hat geschrieben: ↑ zum Beitrag ↑
01.10.2024 23:50:29
3- und 4-Byte-Zeichen sind in UTF-8 wahrscheinlich aehnlich selten wie die erweitereten 4-Byte-Zeichen in UTF-16.
Nein. Alle Smilies, quasi alle chinesischen Zeichen, die meiste Punktuation ist 3-Byte aber in UTF-16 nur 2.
Meiner Recherche nach brauchen Emojis in beiden Encodings 4 Bytes und was ich unter Punktuation verstehe ist grossteils in US-ASCII enthalten, aber was die chinesischen Zeichen angeht (die hier relevanter sind als Emojis), hast du Recht.

debra hat geschrieben: ↑ zum Beitrag ↑
01.10.2024 23:50:29
Deswegen haben wir spekulative Ausführung. Der Rechner nimmt erst mal an, dass es nicht der Fall ist, und macht dann extrem teuer eine Rolle rückwärts, wenn es doch der Fall ist.
debra hat geschrieben: ↑ zum Beitrag ↑
01.10.2024 23:50:29
Weil die Prozesor Hersteller machen halt Statistiken machen, was am häufigsten genutzt wird. Da ist 32 halt ganz vorne und dann 64 und 16Bit. Byte Operationen nicht. Entsprechend optimieren sie ihre Prozessoren, dass die Operationen in einem Takt durch laufen.
Danke fuer die Erklaerungen der hardwarenahen Dinge. Da kenne ich mich nicht so gut aus. Was du beschreibst, ueberzeugt mich.

debra hat geschrieben: ↑ zum Beitrag ↑
03.10.2024 22:07:55
Sonst habe ich mal eine Statistiken zu den Namen, die in der Weltkarte von Osmand auftauchen. (Ich habe vorher uniq drüber laufen lassen, weil viele Flüsse etc in viele gleichnamige Teile aufgeteilt sind.)
Insgesamt 21717221 Zeichen.
Davon

Code: Alles auswählen

17957426 ( 83%) ASCII
 2616854 ( 12%) 2-Byte UTF-8
 1142629 (  5%) 3-byte UTF-8
     312 (.01‰) 4-Byte UTF-8
     313 (.01‰) 4-byte UTF-16
21716908 (100%) 2-Byte UTF-16
 5682050 ( 26%) H, die ich als Trennzeichen verwendet habe
Danke fuer diese Auswertung. Zu meinem Testprogramm bin ich noch nicht gekommen. :roll: Aber du hast das ja schon optimal gemacht. Kannst du den Code des Programms hier posten? Ich wuerde es gerne mal auf deutsche, franzoesische und chinesische Wikipediaseiten anwenden.
debra hat geschrieben: ↑ zum Beitrag ↑
03.10.2024 22:07:55
Es scheint also doch Zeichen zu geben, die 3-Byte in UTF-8 haben und 4 in UTF-16. Eventuell ist da aber auch schlicht ein fehlerhaft codiertes Zeichen im Datensatz.
Zumindest *ein* Zeichen kann in 2-Byte-Zeichen in UTF-16 nicht kodiert werden, denn eine Codestelle muss reserviert sein, um markieren zu koennen, dass dies ein 4-Byte-Zeichen ist. Tatsaechlich sind es aber mehr nicht fuer Zeichen nutzbare Kodierungen, naemlich der Bereich der Surrogates: https://en.wikipedia.org/wiki/UTF-16#U+ ... urrogates)
Diese lassen sich in UTF-8 in 3 Bytes kodieren, in UTF-16 brauchen aber nicht in 2 Bytes.
debra hat geschrieben: ↑ zum Beitrag ↑
03.10.2024 22:07:55
Klar das ist Natürlich ein bisschen fies, weil anteilig viel mehr Texte in englisch/Programmiersprachen... geschrieben sind als Straßennahmen.
Statt ``fies'' wuerde ich sagen, dass das die Realitaet fuer den groessten Teil von digitalem Text auf dieser Welt ist.

Bei diesen Daten braucht UTF-16 deutlich mehr Speicher als UTF-8, naemlich 63% mehr.

Code: Alles auswählen

:-Q bc -ql
17957426*1 + 2616854*2 + 1142629*3 + 312*4
26620269

21716908*2 + 313*4
43435068

43435068/26620269
1.63165398516446246279
Ich vermute, dass dies bei fast allen Texten im Internet so sein wird, solange man nicht ausschliesslich in ostasiatischen Sprachraeumen unterwegs ist.
Use ed once in a while!

debra
Beiträge: 25
Registriert: 27.09.2024 03:12:18

Re: Dateigröße <<< Speicherverbrauch

Beitrag von debra » 16.10.2024 22:15:12

Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
Vielleicht geht es dir auch vor allem um die Fallunterscheidungen, die oefters vorkommen als bei UTF-16.
Ja bit-Operationen kosten meist gar nichts, weil eh irgend welches Memory zeug neben her läuft. Fallunterscheidungen sind extrem teuer, wenn sie falsch vorhergesagt werden.
Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
Meiner Recherche nach brauchen Emojis in beiden Encodings 4 Bytes
Der Emoji Block ja. (Also so Sachen wie 🖍, 💔,🩷) Aber die klassischen Smilies: ♡,☺, ☹... nicht. Ich denke, dass letztere im Web immer noch deutlich häufiger sind.
Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
und was ich unter Punktuation verstehe ist grossteils in US-ASCII enthalten
Kommt drauf an wie sehr man sich beschränkt: Punkt und Komma schon. Aber … „ “– ´ ¬ usw. nicht.


Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
Danke fuer diese Auswertung. Zu meinem Testprogramm bin ich noch nicht gekommen. :roll: Aber du hast das ja schon optimal gemacht. Kannst du den Code des Programms hier posten?
Das Programm hat auch noch obf geparsed und getestet ob das wirklich UTF-8 ist. Und hat sich im lauf der Zeit ein paar mal verändert.
Der relevante Teil:

Code: Alles auswählen

while ((c = fgetc(ifile)) != EOF){
    if(!(c&0x80)){
      onebyte++;
      [...]
      else
        fputc(c,ofile);
      } else if((c&0xe0)==0xc0) {
        twobyte++;
        fallowbytes(1,ifile,ofile,c);
      } else if((c&0xf0)==0xe0) {
        threebyte++;
        fallowbytes(2,ifile,ofile,c);
      } else if((c&0xf8)==0xf0) {
        fourbyte++;
        fallowbytes(3,ifile,ofile,c);
      } else {
        wrong++;
      }
  }
fallowbytes muss in deinem Fall irgend wie so aus sehen (ungetestet). Du kannst die hinteren beiden Argumente auch wegwerfen:

Code: Alles auswählen

void fallowbytes(int count, FILE* ifile, FILE* ofile,int c){
  for(int i=0; i<count; i++)
    fgetc(ifile);
}
Für UTF-16 reich ein Vergleich von wc -c und wc -m: Frei nach Schnauze

Code: Alles auswählen

LANG=C.UTF-8
nc=$(cat file | iconv -t UTF-8 -f UTF-16 | wc -m | cut -d \  -f 1)
fb=$(($(wc -c file | cut -d \  -f 1)/2-$nc))
printf "%6d mal 2 Byte\n" $(($nc-$fb))
printf "%6d mal 4 Byte\n" $fb 
Beachte, dass das nur mit UTF-16 ohne BOM funktioniert.
Mit musst du halt ein

Code: Alles auswählen

tail -c +3 file > /tmp/tmpfile
mv /tmp/tmpfile file
Davor hängen.

Ich wuerde es gerne mal auf deutsche, franzoesische und chinesische Wikipediaseiten anwenden.
Beachte, dass Wikipedia neben UTF-8 auch noch latex escapes und HTML References kennt. Dazu gibt es für vieles Wikimedia eigene Syntax wie WikiHiero für Hieroglyphen. Daneben gibt es je nach Wikipedias noch diverse Sprachspezifische Sachen: Sx wird in Espearnto zu Ŝ aber in der deutschen Wikipedia nicht. Daneben hatte die deutsche Wikipedia mal nen Bot, der &uuml; und &#xea; nach ü konvertiert. Aber kein &#x15c; nach Ŝ... . Da die ganzen escapes alle ASCII sind und auch die Wiki Syntax nicht mit <>,{},[] und = spart, hast du gerne mal mehr [ als „ in nem deutschen Text. Ich wollte das zuerst auch nehmen. Hab dann aber aufgegeben.
Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
Tatsaechlich sind es aber mehr nicht fuer Zeichen nutzbare Kodierungen, naemlich der Bereich der Surrogates: https://en.wikipedia.org/wiki/UTF-16#U+ ... urrogates)
Diese lassen sich in UTF-8 in 3 Bytes kodieren, in UTF-16 brauchen aber nicht in 2 Bytes.
Danke für die Info.
Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
Statt ``fies'' wuerde ich sagen, dass das die Realitaet fuer den groessten Teil von digitalem Text auf dieser Welt ist.
Man bekommt halt nie eine repräsentative Form. Straßennahmen sind halt immer natürliche Sprachen. Oftmals längst ausgestorbene. Bäche und Dörfer hier haben fast immer Althochdeutsch/Alemannische Namen, die heute keiner mehr versteht. Die Straßennamen passen sich an. Als man uns Schwaben erklären wollte, dass man den Genitiv nicht mehr mit ingen bildet haben wir ihn abgeschafft. In Unseren Ortsnahmen lebt er weiter. Genau so wie die Aach bzw. weiter nördlich und östlich die Owe. Repräsentativ für Texte ist das nie gewesen. So viel haben die Germanen nicht niedergeschrieben. A w sind da garantiert massiv überrepräsentiert. ä und d sicher unterrepräsentiert. Umgekehrt ist das HTML, dass man im Web findet eben aber auch nicht repräsentativ für Texte. Denn schon Whatsapp packt nicht mehr alles in <extremlangerasciitag>. Und es gibt auch noch Bücher/PDFs. Alleine die 15 lisp Programme die geschrieben wurden dürften den Anteil an () merklich nach oben getrieben haben. ;-).
Meillo hat geschrieben: ↑ zum Beitrag ↑
14.10.2024 17:12:06
Ich vermute, dass dies bei fast allen Texten im Internet so sein wird, solange man nicht ausschliesslich in ostasiatischen Sprachraeumen unterwegs ist.
Wie gesagt: Noch immer werden die aller meisten Texte im Internet nicht Websiten sein die Unmengen unnötigen ASCII einfügen und ü als &uuml; encodieren.
Chat GPT spuckt mir für Hallo Welt in HTML dasda aus:

Code: Alles auswählen

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hallo Welt</title>
</head>
<body>
    <h1>Hallo Welt</h1>
    <p>Willkommen auf meiner Webseite!</p>
</body>
</html>
Das sind 26 englische Wörter/Abkürzungen und 36 <>/ um 4 deutsche auszuspucken. Und das ist noch harmlos. Auf größeren Websites kommen gerne mal auf wenige hundert Wörter mehrere hundert kiB JavaScript und HTML. Das ist nicht repräsentativ in einer Welt in der nicht mal 20% der Menschen englisch können und noch viel weniger HTML. Klar ist da das Encoding am effizientestens, das die JASM libraries in ein Byte codiert. Und Chrome erkennt das ja sogar schon und lädt die weder runter noch interpretiert sie sondern führt seinen eigenen Code aus, der das selber macht. Nur in deinem Dump taucht sie jedes mal wieder auf.

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Dateigröße <<< Speicherverbrauch

Beitrag von Meillo » 21.10.2024 10:37:41

debra hat geschrieben: ↑ zum Beitrag ↑
16.10.2024 22:15:12
Beachte, dass Wikipedia neben UTF-8 auch noch latex escapes und HTML References kennt. Dazu gibt es für vieles Wikimedia eigene Syntax wie WikiHiero für Hieroglyphen. Daneben gibt es je nach Wikipedias noch diverse Sprachspezifische Sachen: Sx wird in Espearnto zu Ŝ aber in der deutschen Wikipedia nicht. Daneben hatte die deutsche Wikipedia mal nen Bot, der &uuml; und &#xea; nach ü konvertiert. Aber kein &#x15c; nach Ŝ... . Da die ganzen escapes alle ASCII sind und auch die Wiki Syntax nicht mit <>,{},[] und = spart, hast du gerne mal mehr [ als „ in nem deutschen Text.
Wir muessen Transferencodings von Zeichenencodings unterscheiden. Beim Transfer (in Quellcodeform) ist UTF-8 sicherlich am effizientesten weil sowas wie Markup-Tags und Ersatzkodierungen den ASCII-Anteil stark erhoeht. (Ausserdem ist die Byteorderunabhaengigkeit relevant.) Aber darum geht es hier ja nicht.

Transfer- und Ersatzkodierungen sollen hier keine Rolle spielen, d.h. aus den sechs ASCII-Zeichen `&uuml;' wird nach der Transferdekodierung ein Unicode-Zeichen U+00FC (was in UTF-8 und UTF-16 jeweils 2 Bytes benoetigt). Um dieses eine Zeichen in zwei Bytes geht es mir. Ich will also die Wikipedia-Seiten ``rendern'' und dann anschauen, nicht den HTML-Quellcode. ... falls ich jemals dazu komme. :roll:

Meine Vermutung ist weiterhin, dass dieses Ergebnis dann ebenfalls in UTF-8 weniger Speicherplatz braucht als in UTF-16. Fuer den europaeischen Sprachraum sowieso und vermutlich auch fuer den weltweiten Durchschnitt an allesn digitalen Textinhalten. (Ich vermute, dass es insgesamt mehr englischen Text in der digitalen Welt gibt als beispielsweise chinesischen.)

... wobei diese Diskussion letztlich muessig ist, weil sie nur auf Vermutungen basiert und nicht ueberprueft werden kann. Insgesamt haben wir das Thema inzwischen ja doch recht ausfuehrlich beackert ... und ich habe was ueber hardwarenahe vermutungsgetriebene Ausfuehrung gelernt. Auch wenn ich UTF-16 immer noch nicht mag, verstehe ich nun, was du daran sinnvoll findest.
Use ed once in a while!

Antworten