Platzverschwendung im Speicher bei Verwendung von Char Datentypen



  • Hallo,

    ich habe heute mal mit dem Debugger der Visual C++ 6.0 IDE herumgespielt und
    dabei folgendes festgestellt.

    Wenn ich eine char Variable (1 Byte groß) erstelle und danach gleich noch ein paar
    weitere char Variablen erstelle ohne dazu aber ein Array zu verwenden,
    dann verschwende ich Platz im Hauptspeicher.

    Denn für jede einzelne Char Variable wird eine einzige Adresse verwendet,
    wobei die Adresse im Grunde aber bei heutigen 32 Bit Rechnern
    eher als Gruppe von 4 Byte Adressen angesprochen wird (genaugenommen also 4 Adressen) und somit nur 1 byte für diese Gruppenadresse wegen der Char Variable verwendet wird während die restlichen 3 Bytes nicht genutzt werden.

    Im Speicher sieht das dann z.b. so aus
    wenn die char Variable a den Wert 1 hat und die char Variable b den Wert 2:

    Adresse: Wert:
    0068FDF0 01 CC CC CC // Das ist die char Variable a
    0068FDF4 02 CC CC CC // Das wäre die char Variable b die eine eigene Gruppen-Adresse bekommen hat, anstatt diese einfach auf Adresse 0068FDF1 zu legen.

    D.h. in diesem Beispiel werden insgesamt 6 Bytes (der Bereich der den Wert CC hat) verschwendet.

    Wieso wird nur jede 1. Adresse von vier (Gruppen Adresse) für einen char Wert verwendet und nicht auch die 3 weiteren dahinterliegenden Adressen?

    So daß es z.b. so aussieht:
    0068FDF0 01 02 CC CC // eine Gruppen-Adresse für die char Variablen a und b

    So wie das jetzt ist, ist das doch eine reine Platzverschwendung, da
    wundert es mich nun wirklich nicht, wenn die ganzen heutigen Programme
    so aufblähen und einen so hohen Speicherverbrauch haben. 🙄

    Im Grunde spielt es also keine Rolle ob ich nun int oder char Werte verwende,
    da physikalisch gesehen sowieso immer 4 Bytes verwendet werden, ganuz egal ob ein char Wert nur 1 Byte groß ist.
    Und Wenn ich daran denke, das die heutigen Register alle 32 Bit groß sind
    und da dann 4 Byte auf einmal reinpassen kann ich mir auch nicht vorstellen,
    das der Rechner schneller rechnen kann, wenn man z.b. short Ints (2 Byte) anstatt normale 4 byte große Ints verwendet.



  • sdf,

    ist es nicht so, dass der Compiler das extra so
    macht um die Geschwindigkeit zu erhöhen.
    Moderne Prozessoren können 32-Bit Werte um ein
    vielfaches schneller verarbeiten als so kleine
    8- oder 16-Bit Blöcke.
    So steht es zumindest in den Entwickler
    Dokumentationen von AMD.

    Bye Peter.



  • Die ganzen CCs sehen mir sehr nach Debug-Modus aus.



  • sdf schrieb:

    ...Und Wenn ich daran denke, das die heutigen Register alle 32 Bit groß sind und da dann 4 Byte auf einmal reinpassen kann ich mir auch nicht vorstellen, das der Rechner schneller rechnen kann, wenn man z.b. short Ints (2 Byte) anstatt normale 4 byte große Ints verwendet.

    Stimmt, dazu müsste man dann jedes Byte eines Registers einzeln ansprechen können. Oder die CPU organisiert den Zugriff je nach erforderlichem Platz und "beachtet" die anderen Bytes einfach nicht.
    Wir könnten ja mal ne Benchmark für sowas programmieren und gucken, was dabei rauskommt 🙂



  • Ist ja normal, wie bereits hier angesprochen. Ein 32Bit-Prozessor kann nur auf 32 Bit gleichzeitig zugreifen und er kann sich auch nur in 32 Bit-Schritten im Speicher fortbewegen.

    Wenn man einen 8 Bit Prozessor hat, kann man sich dagegen sehr schön in 8 Bit-Schritten bewegen. Aber dafür bekommt ein 8Bit-Prozessor mächtig Performance-Probleme, wenn er mit 32 Bit-Werten hantieren muß. Der 32 Bit-Prozi kann dagegen locker flockig mit 32 Bit-Werten hantieren.

    Alles hat seine Vor- und Nachteile.

    Man kann natürlich auch 4 char in ein Double word (32 Bit) packen, und dann mit Bit-Rotationen und Masking einen gewünschten char rausfiltern. Aber das kostet nunmal auch Arbeit.



  • Wie passt die Tatsache, dass gcc die chars dicht ablegt, in eure tolle Theorie?



  • ich habe heute mal mit dem Debugger der Visual C++ 6.0 IDE herumgespielt

    Muss man noch mehr sagen 😕



  • Artchi schrieb:

    Ein 32Bit-Prozessor kann nur auf 32 Bit gleichzeitig zugreifen und er kann sich auch nur in 32 Bit-Schritten im Speicher fortbewegen.

    Woher hast du denn das? AMD oder Intel Prozis können sich genauso schön in 8 oder 16 bit Schritten bewegen. Ob 32 bit Zugriffe schneller sind als 8 bit wage ich fast zu bezweifeln. 16 bit könnten schon langsamer sein, da mehr Instruction Bytes verarbeitet werden müssen. Viel wichtiger für die Geschwindigkeit ist die Ausrichtung des Speichers.



  • Helium schrieb:

    ich habe heute mal mit dem Debugger der Visual C++ 6.0 IDE herumgespielt

    Muss man noch mehr sagen 😕

    Wo soll da das Problem sein?

    Der Debugger zeigt mir die Register und den Speicherinhalt an,
    ich finde das äußerst praktisch.



  • Bashar schrieb:

    Wie passt die Tatsache, dass gcc die chars dicht ablegt, in eure tolle Theorie?

    Habs zwar noch nicht nachgeprüft, aber wenn das so wäre, dann wäre das klasse, denn das würde auch erklären warum der gcc beim Compilieren mehr
    Zeit benötigt als der Visual C++ Compiler, denn in diesem Fall geht der GCC ordernlichter vor, d.h. der Maschinencode ist hinterher sauberer und nicht so verschwenderisch wie beim Visual C++ Compiler.



  • sdf schrieb:

    Bashar schrieb:

    Wie passt die Tatsache, dass gcc die chars dicht ablegt, in eure tolle Theorie?

    Habs zwar noch nicht nachgeprüft, aber wenn das so wäre, dann wäre das klasse, denn das würde auch erklären warum der gcc beim Compilieren mehr
    Zeit benötigt als der Visual C++ Compiler, denn in diesem Fall geht der GCC ordernlichter vor, d.h. der Maschinencode ist hinterher sauberer und nicht so verschwenderisch wie beim Visual C++ Compiler.

    Blödsinn.
    Ob der Compiler jetzt ein char zu einem DWORD 'padded' oder nicht, ist von der Dauer wohl irrelevant.

    Dass der gcc sehr schnellen Code erzeugt, dürfte wohl klar sein.

    Der Grund warum er so langsam ist, ist der interne Aufbau. GCC ist ja eine Sammlung von Compilern, man kann eine neue Sprache implementieren ohne einen vollständigen Compiler zu schreiben - im Prinzip muss man nur ein Frontend implementieren - der Rest wird vom GCC übernommen.

    Dieses Konzept bedeutet, dass der GCC extrem Portabel ist, da man nur ein Backend für einen neuen Prozessor schreiben muss, und schon laufen alle GCC Sprachen dort 😉

    Allerdings ist er dadurch natürlich wieder langsamer. Und wenn ich mir den Trend so ansehe, ist Geschwindigkeit beim GCC nicht so wichtig.



  • Shade Of Mine schrieb:

    sdf schrieb:

    Bashar schrieb:

    Wie passt die Tatsache, dass gcc die chars dicht ablegt, in eure tolle Theorie?

    Habs zwar noch nicht nachgeprüft, aber wenn das so wäre, dann wäre das klasse, denn das würde auch erklären warum der gcc beim Compilieren mehr
    Zeit benötigt als der Visual C++ Compiler, denn in diesem Fall geht der GCC ordernlichter vor, d.h. der Maschinencode ist hinterher sauberer und nicht so verschwenderisch wie beim Visual C++ Compiler.

    Blödsinn.
    Ob der Compiler jetzt ein char zu einem DWORD 'padded' oder nicht, ist von der Dauer wohl irrelevant.

    Also ich sehe das anders.
    Es wird einem zwar immer mehr Speicher geradezu nachgeschmissen,
    aber die Anwendungen brauch insgesammt ebenfalls immer mehr Speicher,
    d.h. das summiert sich auf und Speicher ist damit sozusagen immer ein knappes Gut, deswegen sollte man sparsam mit ihm umgehen.

    Dass der gcc sehr schnellen Code erzeugt, dürfte wohl klar sein.

    Es ging nicht darum, ob er schnellen Code erzeugt sondern darum wie lange er dazu braucht.

    Der Grund warum er so langsam ist, ist der interne Aufbau. GCC ist ja eine Sammlung von Compilern, man kann eine neue Sprache implementieren ohne einen vollständigen Compiler zu schreiben - im Prinzip muss man nur ein Frontend implementieren - der Rest wird vom GCC übernommen.

    Danke für die Info.



  • sdf schrieb:

    Shade Of Mine schrieb:

    sdf schrieb:

    Bashar schrieb:

    Wie passt die Tatsache, dass gcc die chars dicht ablegt, in eure tolle Theorie?

    Habs zwar noch nicht nachgeprüft, aber wenn das so wäre, dann wäre das klasse, denn das würde auch erklären warum der gcc beim Compilieren mehr
    Zeit benötigt als der Visual C++ Compiler, denn in diesem Fall geht der GCC ordernlichter vor, d.h. der Maschinencode ist hinterher sauberer und nicht so verschwenderisch wie beim Visual C++ Compiler.

    Blödsinn.
    Ob der Compiler jetzt ein char zu einem DWORD 'padded' oder nicht, ist von der Dauer wohl irrelevant.

    Also ich sehe das anders.
    Es wird einem zwar immer mehr Speicher geradezu nachgeschmissen,
    aber die Anwendungen brauch insgesammt ebenfalls immer mehr Speicher,
    d.h. das summiert sich auf und Speicher ist damit sozusagen immer ein knappes Gut, deswegen sollte man sparsam mit ihm umgehen.

    Da gibt es nichts anders zu sehen. Es ist von der Übersetzungszeit her irrelevant, ob der Compiler die Bytes zusammensteckt oder nicht.
    Der Rest paßt irgendwie grad nicht zum Thema.



  • Bashar schrieb:

    Wie passt die Tatsache, dass gcc die chars dicht ablegt, in eure tolle Theorie?

    Vielleicht weil es eine Option gibt, die sowas erlaubt? In VC++ Professionell kann man wählen, ob der Code "schnell" oder "platzsparend" arbeiten soll. Wobei schnell bedeuten kann, das mehr Speicher belegt wird. Und platzsparend evtl. langsamen Code.

    So kenne ich es vom VC++ Pro.



  • groovemaster2002 schrieb:

    Artchi schrieb:

    Ein 32Bit-Prozessor kann nur auf 32 Bit gleichzeitig zugreifen und er kann sich auch nur in 32 Bit-Schritten im Speicher fortbewegen.

    Woher hast du denn das? AMD oder Intel Prozis können sich genauso schön in 8 oder 16 bit Schritten bewegen. Ob 32 bit Zugriffe schneller sind als 8 bit wage ich fast zu bezweifeln. 16 bit könnten schon langsamer sein, da mehr Instruction Bytes verarbeitet werden müssen. Viel wichtiger für die Geschwindigkeit ist die Ausrichtung des Speichers.

    Na gut, wenn du meinst, das auf diesem Planeten nur AMD und Intel existiert? Ich weiß nicht ob diese CPUs auch 8 Bit-Zugriffe erlauben. Ich weiß nur, das die ARM-Familie z.B. nur 32 Bit-Zugriffe erlaubt, und dadurch irrsinnig schnell ist.

    OK, da die heutigen Intels zu 20 Jahre alten 8086 kompatibel sein müssen, kann es gut sein, das da noch 8 Bit-Befehle und Register umkriechen. Technik die Begeistert! 😃



  • sdf schrieb:

    Helium schrieb:

    ich habe heute mal mit dem Debugger der Visual C++ 6.0 IDE herumgespielt

    Muss man noch mehr sagen 😕

    Wo soll da das Problem sein?

    Der Debugger zeigt mir die Register und den Speicherinhalt an,
    ich finde das äußerst praktisch.

    Ja aber der Debugger packt auch tonnenweise Kram in den Code, der im Release nicht mehr da ist.

    01 CC CC CC

    Noch eindeutiger geht's kaum. CC CC CC stammt garantiert vom Debuggen.



  • Helium schrieb:

    sdf schrieb:

    Helium schrieb:

    ich habe heute mal mit dem Debugger der Visual C++ 6.0 IDE herumgespielt

    Muss man noch mehr sagen 😕

    Wo soll da das Problem sein?

    Der Debugger zeigt mir die Register und den Speicherinhalt an,
    ich finde das äußerst praktisch.

    Ja aber der Debugger packt auch tonnenweise Kram in den Code, der im Release nicht mehr da ist.

    Und wie schau ich mir den Code dann nach dem Release an?



  • sdf schrieb:

    Und wie schau ich mir den Code dann nach dem Release an?

    Lass dir den ASM Code generieren und schau den an 😉



  • mein gcc-Testprogramm sah übrigens so aus:

    #include <iostream>
    using namespace std;
    int main()
    {
      char a,b;
      cout << &a - &b << endl;
    }
    

    abhängig von den Optimierungseinstellungen kam -1 oder 1 raus.

    BTW wenn es tatsächlich so wär, dass Bytes auf 32bit ausgerichtet schneller verarbeitet werden können, warum ist dann ein char nicht 32bit groß? Compiler sollten diesen Modus der Geschwindigkeit wegen wenigstens anbieten.



  • Artchi schrieb:

    Na gut, wenn du meinst, das auf diesem Planeten nur AMD und Intel existiert?

    Warum legen einige Leute nur jedes Wort auf die Goldwaage? Sry wenn ich dir mit meiner Aussage impliziert hab, dass ich nur AMD und Intel Prozis kenne. Dem ist natürlich nicht so. Aber ich gehe mal davon aus, dass die meisten der Forumuser einen der 2 Prozis in ihrem Rechner haben.

    Artchi schrieb:

    OK, da die heutigen Intels zu 20 Jahre alten 8086 kompatibel sein müssen, kann es gut sein, das da noch 8 Bit-Befehle und Register umkriechen.

    Dem ist nicht so, weil die Prozessoren zu 20 Jahren alten kompatibel sein müssen. Sondern weil die 8 bit Register Teil der 32 bit Register sind. Und wenn sie schon da sind, warum dann nicht auch nutzen.


Anmelden zum Antworten