Christian S.: Base64 codiertes JavaScript.

Hi,

habe gerade den /packer/ gefunden und frage mich wie diese Base64 Codierung funktioniert.

JavaScript durch entfernen von Whitespaces und Kommentaren und auch noch die Ersetzung von Variablen durch kürzere ist ja noch nachvollziehbar.

Aber der Code der bei der Base64 Codierung entsteht, ist zu hoch für mich....

Kann einer erklären, was dahinter steckt?

Und eine sehr wichtige Frage:

kostet das irgendwie Performance für den JS Interpreter? Der muss ja da irgendwie so ein eval erst mal machen und das kostet sicher, oder?

Gruß
Christian

  1. Google ist dein Freund: Base64 ist einfach nur eine Art, beliebige Daten mit einem Zeichensatz von nur 64 Zeichen (plus einem Padding-Zeichen) darzustellen. Dabei werden die Daten allerdings um ca. ein Drittel aufgebläht.

    Ohne die verlinkte Seite auch nur gesehen zu haben gehe ich mal schwer davon aus, das der Autor einen sehr kompakten Base64-Dekoder mit eval() o.ä. kombiniert, um Javascript-Code zu verschleiern. Wahlweise wäre auch eine data:-URL in <script src=...> nach RFC2397 möglich, das versteht aber nicht jeder Browser.

    Sinnlos, sich damit weiter zu beschäftigen. Javascript-Code kompakter zu machen, um Übertragungszeit auf langsamen Leitungen oder stark belasteten Servern zu sparen, klingt ja noch ansatzweise sinnvoll, aber 30% Overhead nur um zu verhindern, dass Kiddies Javascript-Code kopieren, ist absolut schwachsinnig.

    Alexander

    1. Hi,

      Sinnlos, sich damit weiter zu beschäftigen. Javascript-Code kompakter zu machen, um Übertragungszeit auf langsamen Leitungen oder stark belasteten Servern zu sparen, klingt ja noch ansatzweise sinnvoll, aber 30% Overhead nur um zu verhindern, dass Kiddies Javascript-Code kopieren, ist absolut schwachsinnig.

      was für 30% Overhead? Mir geht es auch in erster Linie um Performance, nicht darum, dass ich nicht will dass jemand code klaut.

      meinst du Base64 bläht den Code um 30% auf?? also bei dem /packer/ ists eher das Gegenteil, er wird ca. um 50% kleiner.

      Gruß!

      1. Hi,

        was für 30% Overhead?

        die, die Alexander gleich im ersten Absatz seines Postings nannte. Die, die bei Base64 zwangsläufig vorhanden sind.

        Mir geht es auch in erster Linie um Performance,

        Welchen Zusammenhang siehst Du zwischen Deiner Frage und der Performance?

        nicht darum, dass ich nicht will dass jemand code klaut.

        Das ist gut, denn das ließe sich nicht verhindern.

        meinst du Base64 bläht den Code um 30% auf??

        Nein, das meint er nicht. Er weiß es.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hi,

          Welchen Zusammenhang siehst Du zwischen Deiner Frage und der Performance?

          ok, eigentlich wollte ich eher wissen, wie das verfahren auf /packer/ funktioniert. Da es ja offensichtlich >50% einspart, statt 30% hinzufügt. und da auch noch mit RegExp und eval rumhantiert wird.
          Der string der entsteht sieht auch nicht aus, wie ein typischer Base64 string.

          und der weitere Gedanke war:
          ~50% weniger Code = kleinere Datei => Seite lädt schneller => höhere Performance.

          bzw. das war nicht der weitere Gedanken, sondern der Gedanken den ich schon vorher hatte.

          Gruß
          Christian

          1. Hi,

            ok, eigentlich wollte ich eher wissen, wie das verfahren auf /packer/ funktioniert.

            der Quellcode ist einsehbar, welche Fragen dazu hast Du?

            Da es ja offensichtlich >50% einspart, statt 30% hinzufügt. und da auch noch mit RegExp und eval rumhantiert wird.
            Der string der entsteht sieht auch nicht aus, wie ein typischer Base64 string.

            Nein, es handelt sich dort auch nicht um Base64-Kodierung, die übrigens nirgends erwähnt wird.

            und der weitere Gedanke war:
            ~50% weniger Code = kleinere Datei => Seite lädt schneller => höhere Performance.

            In dem Moment, in dem das Script so groß ist, dass sich dies lohnen würde, ist die zum Entpacken benötigte Verarbeitungszeit so groß, dass sie den User mehr belasten wird als die höhere Ladezeit.

            Cheatah

            --
            X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
            X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. Lieber Cheatah,

              In dem Moment, in dem das Script so groß ist, dass sich dies lohnen würde, ist die zum Entpacken benötigte Verarbeitungszeit so groß, dass sie den User mehr belasten wird als die höhere Ladezeit.

              Ich habe den Test gemacht.

              tiny_mce_src.js (206KB) in die Textarea gepastet

              • base62-Kodierung
              • Variablenverkürzung

              Packvorgang: 6,5 Sekunden, "compression ratio: 88041/211416=0.416"

              Entpackvorgang: "unpacked in 172 milliseconds, compression ratio: 137978/211416=0.653"

              Was sagst Du nun?

              Liebe Grüße aus Ellwangen,

              Felix Riesterer.

              --
              ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
              1. Packvorgang: 6,5 Sekunden, "compression ratio: 88041/211416=0.416"

                Das sagt aus, das der Server an 200 kByte Code schon mächtig zu knabbern hat. Die Komprimierung auf etwa 40% ist schon nicht schlecht, aber GZIP und WinZIP packen deutlich besser (52.472 Bytes bzw. 54.135 Bytes), bzip2 sogar bis auf 44.222 Bytes -- und alle drei packen verlustlos, alle Namen, alle Einrückungen, alle Kommentare bleiben erhalten.  Und alle drei schaffen das unter einer Sekunde auf der antiquierten Hardware, die ich gerade greifbar habe. Mit dem Base64-typischen Overhead kommt bzip2 auf 59.740 Bytes, immer noch unter einer Sekunde und immer noch kleiner als das Ergebnis des verlinkten Programms.

                Entpackvorgang: "unpacked in 172 milliseconds, compression ratio: 137978/211416=0.653"

                Das lese ich so, das das Endergebnis nach dem "Auspacken" um 40% verkleinert wurde, vermutlich durch massives Löschen von Teilen des ursprünglichen Quelltextes.

                Außerdem dürfte der Computer, auf dem der Browser läuft, ein flottes Maschinchen sein.

                Was sagst Du nun?

                Ich sage: Vorkomprimiert auf dem Server ist diese Datei schneller und dichter mit gzip gepackt als mit dem verlinkten Programm, dazu können die meisten Browser gzip transparent entpacken. Mit einem geeigneten Programm auf dem Server (mod_gzip, gzip_cnc) kann je nach Fähigkeiten des Browsers die komprimierte oder die unkomprimierte Version ausgeliefert werden.

                In einer Vorstufe kann man außerdem vor der Übertragung vom Entwicklungssystem auf das Produktivsystem Kommentare und unnötigen Whitespace entfernen, das würde die Datei noch weiter verkleinern.

                Alexander

                1. Mal allgemein ne Frage zu gzip:

                  Braucht das nicht auch Performance auf dem Server, um die JS Datei erst mal zu komprimieren und dann wieder Zeit auf dem Client, um sie wieder zu dekomprimieren?

                  Generell sagt mir doch mein logischer Menschenverstand: ja!

                  Dann "komprimier" ich sie doch lieber durch entfernen von Whitespaces, Kommentaren und Variablenverkürzung. Das ist ja dann keine echte Komprimierung, wofür man noch einen Algorithmus anwenden muss.

                  Gruß
                  Christian

                  1. Hi,

                    Braucht das nicht auch Performance auf dem Server, um die JS Datei erst mal zu komprimieren

                    ja, aber wenig, und i.d.R. ist das Ergebnis cachebar.

                    und dann wieder Zeit auf dem Client, um sie wieder zu dekomprimieren?

                    Ja, aber das geschieht nicht durch JavaScript und ist somit rasend schnell.

                    Cheatah

                    --
                    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
                    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
                    X-Will-Answer-Email: No
                    X-Please-Search-Archive-First: Absolutely Yes
                    1. ja, aber wenig, und i.d.R. ist das Ergebnis cachebar.

                      Genau das macht gzip_cnc. "Das Programm verwendet Content-Negotiation zur Feststellung, ob der Web-Browser bereit ist, gzip-codierte Inhalte zu empfangen, und speichert für jedes ausgelieferte Dokument die aktuellste Version des Inhalts in komprimierter Form innerhalb seines eigenen Cache-Baums." (Quelle: http://schroepl.net/projekte/gzip_cnc/)

                      Das Javascript wird also exakt EINMAL mit dem in C geschriebenem gzip-Code komprimiert, danach muß gzip_cnc nur noch anhand EINES EINZIGEN HTTP-Headers entscheiden, ob das Original oder die komprimierte Fassung ausgeliefert wird. Wird das Original verändert, wird des erneut und vollautomatisch komprimiert, ohne dass man auch nur an die Komprimierung denken muß.

                      und dann wieder Zeit auf dem Client, um sie wieder zu dekomprimieren?

                      Ja, aber das geschieht nicht durch JavaScript und ist somit rasend schnell.

                      Dem ist nichts mehr hinzuzufügen.

                      Alexander

              2. Hi,

                Ich habe den Test gemacht.

                ich habe ihn mal wiederholt, obwohl bereits Alexander den scheinbaren Erfolg als Misserfolg entlarvt hat.

                Packvorgang: 6,5 Sekunden, "compression ratio: 88041/211416=0.416"

                Packvorgang: Mein Browser meldet mir zwei(!) mal, ein Script würde ihn blockieren und fragt mich, ob ich es abbrechen möchte. Mein Firmenrechner ist übrigens im Vergleich zu anderen recht gut ausgestattet.

                Entpackvorgang: "unpacked in 172 milliseconds, compression ratio: 137978/211416=0.653"

                Entsprechend braucht das Entpacken auch locker eine halbe Sekunde. In dieser halben Sekunde *steht der gesamte Browser still* und widersteht jedem Versuch, ihn zu bedienen. Im Realbetrieb ist noch mit höheren Zeitwerten zu rechnen, da der Vorgang auf einer sehr simpel gebauten Seite außerhalb einer Phase geschieht, in der der Browser (wie z.B. beim Ladevorgang) zusätzlich mit anderen Dingen beschäftigt ist.

                Was sagst Du nun?

                Ich sage, dass Du nur mit Deiner Kiste angeben möchtest ;-)

                Cheatah

                --
                X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
                X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
                X-Will-Answer-Email: No
                X-Please-Search-Archive-First: Absolutely Yes
                1. Packvorgang: Mein Browser meldet mir zwei(!) mal, ein Script würde ihn blockieren und fragt mich, ob ich es abbrechen möchte.

                  Gratulation. Meiner hat sich nach ein paar Sekunden Bedenkzeit den Stick genommen und danach seinen Kadaver von der Betriebssystem-Attrappe aus dem Speicher befördern lassen.

                  Alexander

          2. Lieber Christian,

            ich weiß ja nicht, was Du da liest, aber bei mir steht da etwas von base62, nicht etwa von base64.

            Zur Funktionsweise:
            Ich verstehe davon nix. Nur soviel, dass mittels diverser Einsparungen an entbehrlichen Zeichen der String verkürzt wird. Danach werden alle Zeichen des Strings in base62-kodierte Zeichen umgeschrieben. Dieser base62-kodierte String wird mittels eines Wörterbuches nach einem anscheinend relativ üblichen Mechanismus (ZIP?) gepackt. Erst in diesem Schritt entsteht die tatsächliche Einsparung.

            Diese Einsparung kann man im Vorfeld möglicherweise noch erhöhen, wenn man die Variablennamen neu generieren lässt. Allerdings hatte das in meinem Test keine spürbare Einsparung gebracht.

            Mir scheint es allerdings so zu sein, dass erst durch das Kodieren in base62 ein Daten-Overhead entsteht (prinzipbedingt), der sich aber durch die auf 62 verschiedene Zeichen begrenzten Zeichenfolgen in sehr guter Art und Weise komprimieren lässt, sodass der anfängliche Overhead mehr als wieder wett gemacht wird.

            Liebe Grüße aus Ellwangen,

            Felix Riesterer.

            --
            ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)