Performancevergleich von C, C++, MS VC++, VB6 und noch einige Fragen!



  • Redhead schrieb:

    Hast du denn mal mit nem Profiler geprüft wo denn die Performance-Probleme von deinem Programm wirklich liegen. Ansonsten ist das hier ne mehr oder weniger
    philosophische Diskussion, die dir bei deinem konkreten Problem nicht wirklich weiterhilft.

    Nein habe ich noch nicht, allerding weiß ich auch ganz genau wo die Flaschenhälse in meinem Programm liegen. Das erste ist die relativ häufige Verwendung von Byte-Operationen und dem Herumschieben der Bytes und das Zweite ist das relativ häufige herausschneiden und wiedereinfügen von Zeichen in den Strings mit der Mid-Funktion und das ist bei den variablen Listen-Strings in VB nicht das Optimum.

    @Badestrand: Ich habe dir die Mail vor ca. 10 Minuten geschickt.

    @hustbaer: D.h. ich sollt, wenn ich dynamische Datenstrukturen brauche, auf die Vectoren anstatt der Listen zurückgreifen und prinzipiell die Strings mit fester Länge in einem Array speichern?

    da kams schrieb:

    nenn doch mal ein paar details zu deinem alogrithmus, denn es hört sich nach wie vor interessant an.

    Gut, ich habe einfach die Teile die sich mit dem Algorithmus beschäftigen aus dem File, das ich an Badestrand geschickt habe, herauskopiert. Es könnte sein, dass das Ganze jetzt ein bißchen aus dem Zusammenhang gerissen ist, aber ihr könnt ja gerne fragen, wenn ihr welche habt.

    Grundlegendes:
    Prinzipiell wurde das Programm zur Kompression von Zahlenreihen entworfen, da unser SQL-Server von diesen Daten zugemüllt wird. (In den letzten 3 Jahren waren es ungefähr 110GB.) Diese Daten sind Messdaten von Gießmaschinen wobei immer der Druck, die Geschwindigkeit und der Weg alle 1/1500 Sekunden gemessen werden. (Solche Daten kannst du dir z.B. in den angehängten Dateien Druck.txt, Speed.txt und Weg.txt anschauen.)

    Prinzipielle Funktionsweise des Algorithmus:
    Zurzeit besteht der Algorithmus aus 5 „Stufen“ auf die ich jetzt näher eingehen werde. Zum besseren Verständnis werde ich den folgenden Messdaten-String immer zum Erläutern von Beispielen verwenden: 0.00;3.44;6.66;6.48;6.66;2.42;0.00;

    1. Relative Änderungen berechnen:
    In diesem Schritt werden aus den absolut Werten der Messreihe die relativen Änderungen berechnet, d.h. es wird immer nur der Unterschied zum nächsten Messwert berechnet, z.B. aus 0.00;3.44;6.66;6.48;6.66;2.42;0.00; wird 0.00;3.44;3.22;0.18;-4.24;-2.42;. Das sieht für unseren Beispiel-String jetzt nicht nach einer großartigen Komprimierung aus, jedoch verhalten sich die Messdaten in der Praxis meist so, dass sie zu Beginn der Messung kontinuierlich steigen, danach die meiste Zeit ziemlich konstant bleiben und am Ende wieder auf 0 fallen, z.B.: der Druck pendelt sich meist um die 300 Bar ein. Wenn ich jedes Mal die absoluten Werte z.B. 310.04;310.12;310.22; speichern würde, würde ich im Vergleich zu den relativen Änderungen 310.04;0.08;0.1; ziemlich viel Platz verbraten.

    2. Trimmen und unnötige Nullen entfernen
    Hier wird der gesamte String von Leerzeichen befreit, meist sind zwar keine bzw. fast keine vorhanden, aber sicher ist sicher. Außerdem werden alle unnötigen Nullen entfernt z.B.
    0.00 -> 0 oder 1.10 -> 1.1 oder 02.00 -> 2 oder 0.34 -> .34 oder ;0;0;0;0;0; -> ;;;;;. D.h. aus unseren Beispiel-String aus dem bereits die relativen Werte berechnet wurde 0.00;3.44;3.22;0.18;4.24;0.00; wird nun 0;3.44;3.22;.18;4.24;0;

    3. Aufeinanderfolgende gleiche Zeichen komprimieren
    Relativ oft, speziell beim Druck, ergibt sich die Situation, dass sich keine Änderung ergibt, d.h. es würde ca. so etwas nach der Berechnung der relativen Änderungen dastehen: ;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;. Nach dem entfernen der Nullen würde der String so aussehen ;;;;;;;;;;;;;;;;. Nun habe ich mir eine gesonderte Darstellung solcher Wiederholungen ausgedacht und zwar x;16;. Das x dient hier als Steuerzeichen und weißt daraufhin, dass das nächste Zeichen, der Strichpunkt, mehrmals vorkommt und zwar genauso oft wie die darauf folgende Zahl (16). Dies zahlt sich jedoch nur bei Folgen von mindestens 5 gleichen Zeichen aus, da ich mindestens 4 Zeichen zur Darstellung dieser Folge brauche, z.B. x;3; währe unnötig da sich die drei Strichpunkte mit 3 Zeichen darstellen lassen würde, ich jedoch für die Codierung mindestens 4 Zeichen brauche.

    4. Codierung auf 4 Bit pro Zeichen
    Da wir prinzipiell nur Zahlenreichen darstellen brauchen wird keine 8 Bit zur Darstellung eines Zeichens, da wir nur 10 Zahlen, ein Minus (als Vorzeichen bei einer negative relativen Änderung), ein Trennzeichen (;), ein Steuerzeichen für die Folgen (x) und ein Platzhalterzeichen. Warum wir auch einen Platzhalter brauchen erkläre ich gleich. D.h. in Summe verwenden wir 14 Zeichen. Diese 14 unterschiedlichen Zeichen / Werte lassen sich jedoch bereits mit 4 Bit darstellen und wir brauchen keine 8 Bits zur Darstellung, da dies relativ unnötig wäre. D.h. wir codieren alle unsere Zeichen von der 8 Bit Darstellung auf eine 4 Bit Darstellung. Der Platzhalter dient dazu um das Byte am Ende vollständig zu machen, z.B. wenn bei der letzten Codierung nur ein halbes Byte befüllt wird, wird der Platzhalter eingefügt um das Byte vollständig zu machen. Das Problem an dieser Codierung ist, dass sie von den 5 Komprimierungsschritten mit Abstand am längsten braucht, da ich hier relativ viel mit Bits und Bytes herumschaufle und das ist, wie hustbaer bereits im Forum gesagt hat, in VB ziemlich langsam, jedoch will ich diesen Schritt nicht einfach streichen, da er mir immer eine konstante Kompressionsrate von 50% bringt.

    5. LZW-Kodierung durchführen
    Hier wird einfach das LZW-Kodierungsverfahren auf den Ergebnisstring angewandt, wobei man hier auf der Benutzeroberfläche 2 unterschiedliche Verfahren auswählen kann. Die 1. Methode ist eine von uns angepasste Version des LZWs und bringt im Normalfall auch die bessere Kompression. Die 2. Methode ist eine 1:1 Kopie einer Implementierung des LZW-Verfahrens aus dem Internet.

    Kleiner Ausblick auf die Zukunft:
    Prinzipiell habe ich vor noch die Huffman-Kodierung einzusetzen, jedoch habe ich bis jetzt im Internet noch nichts Brauchbares gefunden (Naja, ich habe auch noch nicht wirklich intensiv gesucht). Falls ihr eine Bibliothek oder ähnliches kennt in der dieses Verfahren implementiert ist, schreibt mir bitte. Außerdem habe ich noch ein paar Ideen basierend auf Multithreading die ich jedoch wahrscheinlich nicht in den 2 Wochen, die ich noch Zeit habe, umsetzen kann. Weiters habe ich noch ein paar Idee für ein „intelligentes“ Programm das im vorhinein weis welcher Schritt eine Kompression bringt und danach entscheidet ob es den Aufwand (zeitlich gesehen) rechtfertigt um diesen Schritt durchzuführen.

    Ich hoffe ich konnte euch das Ganze einigermaßen verständlich erklären. Falls ihr noch ein paar Fragen zum Algorithmus oder Ideen zur Verbesserung hast könnt ihr mir sie gerne schicken!



  • Du liest den kompletten Datensatz (Größe?) ein, komprimierst/veränderst den "String" und speicherst den dann wieder komplett an einem Stück?

    Und welcher der 5 Schritte ist der Flaschenhals?



  • Tellerrand schrieb:

    Du liest den kompletten Datensatz (Größe?) ein, komprimierst/veränderst den "String" und speicherst den dann wieder komplett an einem Stück?

    Und welcher der 5 Schritte ist der Flaschenhals?

    Zurzeit ist es wirklich so, dass ich die gesamte Datei auf einmal einlese und komprimiere. Jedoch wird sich das dahingehend ändern, dass ich eine Zeile (und damit eine komplette Mess- und Datensatzreihe einlese und komprimiere) und dann die nächste. Wobei eine Messreihe ca. die Größe von 1000-2000 Zeichen hat.

    Oh sorry, hab ich vergessen zu schreiben. Der Flaschenhals liegt im 4. Schritt, der Codierung auf die 4 Bit, da ich dort wie oben gesat, ziemlich oft die mid-Funktion und Byte-Operationen brauche.

    mfg



  • Sorry, hatte das überlesen.

    Possessed schrieb:

    Zur Zeit sieht es so aus:
    Das Programm liest eine Datei ein (zurzeit noch komplett, später wird man die Größe die eingelesen werden soll angeben können z.B: 50MB). Danach wird die eingelesene Datei in 8KB Stücke zerhäckselt und die einzelnen Stücke der Komprimierungsfunktion vorgeworfen. (Eine Erklärung warum die 8KB ist relativ schwierig, wobei ich auch dafür wäre die Größe zu erhöhen um die Funktion (die hoffentlich bald in einer DLL ist) seltener aufzurufen, aber da muss ich noch mit meinem big boss reden). Nachdem die einzelnen Stücke wieder aus der Komprimierungsfunktion zurückkommen werden sie wieder zu einem langen String zusammengestoppelt und in eine Datei geschrieben. (Dies sollte nur kurz zur ungefähren erläuterung des programmes dienen.)

    Meiner Meinung nach würdest du bessere Ergebnisse erreichen, wenn du mit gepufferten Datenströmen arbeiteten würdest. Also anstatt alles zu lesen, in einen String zu packen, verarbeiten und dann zu speichern könnte man an vielen Stellen auch folgendes machen.
    Zum Beispiel für Schritt Nr. 3, Pseudo Code:

    leseZEichen liest halt aus dem Eingabestrom
    schreibeZeichen schreibt in den Ausgabestrom
    
    x = leseZeichen
    c = 1;
    while( (y = leseZeichen) == x) { c++ }
    if(c > 4) {
      schreibeZeichen("x")
      schreibeZeichen(c)
      schreibeZeichen(x)
    }else {
      while(c > 0) {
        schreibeZeichen(c)
        c--
      }
    }
    wieder von vorne mit x = y ;)
    

    Nur mal schnell dahin getipt und ehrlich gesagt habe ich auch keine Ahnung wie man sowas in VB ordentlich machen sollte 😉
    Nur einen String von Beispielsweise 50MB in 8KB Stücke zu zerhäckseln und dann darin zu arbeiten stelle ich mir recht aufwändig vor und würde solche String Operationen einfach meiden. Stückweise vorgehen ist da oftmals flotter und garantiert fast immer eine lineare Komplexität.



  • Danke für die Mail! Ich werd mir den Text heute Abend in aller Ruhe genehmigen. Wirklich vielen vielen Dank für die Mühe! 🙂



  • Tellerrand schrieb:

    Sorry, hatte das überlesen.

    Meiner Meinung nach würdest du bessere Ergebnisse erreichen, wenn du mit gepufferten Datenströmen arbeiteten würdest. Also anstatt alles zu lesen, in einen String zu packen, verarbeiten und dann zu speichern könnte man an vielen Stellen auch folgendes machen.
    Zum Beispiel für Schritt Nr. 3, Pseudo Code:

    leseZEichen liest halt aus dem Eingabestrom
    schreibeZeichen schreibt in den Ausgabestrom
    
    x = leseZeichen
    c = 1;
    while( (y = leseZeichen) == x) { c++ }
    if(c > 4) {
      schreibeZeichen("x")
      schreibeZeichen(c)
      schreibeZeichen(x)
    }else {
      while(c > 0) {
        schreibeZeichen(c)
        c--
      }
    }
    wieder von vorne mit x = y ;)
    

    Nur mal schnell dahin getipt und ehrlich gesagt habe ich auch keine Ahnung wie man sowas in VB ordentlich machen sollte 😉
    Nur einen String von Beispielsweise 50MB in 8KB Stücke zu zerhäckseln und dann darin zu arbeiten stelle ich mir recht aufwändig vor und würde solche String Operationen einfach meiden. Stückweise vorgehen ist da oftmals flotter und garantiert fast immer eine lineare Komplexität.

    Prinzipiell arbeite ich so wie in deinem Pseudocode beschrieben, außer das ich die Zeichen gleich wieder in eine Datei schreiben. Das Problem daran ist, dass ich es nicht gleich wieder hinausschreiben kann, da ich den komprimierten String wieder als Eingangsstring für den nächsten Schritt brauche, daher kann ich ihn nicht gleich hinausschreiben, sondern muss mir gezwungenermaßen wieder einen neuen String zusammenbasteln und den der nächsten Komprimierungsfunktion vorwerfen.

    Obwohl 8KB stimmt auch nicht mehr, zurzeit arbeite ich mit 2KB, allerdings werde ich das wieder erhöhen. Schlussendlich wird es sich irgendwo zwischen 5-10KB einpendeln. Das Problem an der Größe ist, dass ich im String gewisse Häufigkeiten brauche im überhaupt etwas komprimieren zu können (dieses Argument spricht eher für große Fragmentgrößen), andererseits versuch mal in einem String mit 10.000 Zeichen zu debuggen und das ordentlich nachzuvollziehen (das spricht wiederum für kleinere Fragmente).

    Allerdings lese ich den ganze String ein und zerschneide sie dann in die Fragmente (und erzeuge damit wieder einen neuen String), was eigentlich ziemlich dumm ist. Da ich zurzeit allerdings mit relativ kleinen Datein (ca. 50-250KB) arbeite ist mir das performancemäßig noch garnicht aufgefallen. Werde das so aumbauen, dass ich nur die Fragmentgröße einlese und nicht gleich die ganze Datei.

    Aber wie gesagt, der dritte Schritt ist nicht das Problem. Das Problem ist der 4. Schritt mit den vielen String-Funktionen in den dynamischen Strings von VB. (Das verbrät ungefähr 75-80% der Zeit. Da ist der 3. Schritt mit ca. 3-5% ziemlich gut dran.) Da ich aber sowieso vorhabe das ganze auf MS VC++ zu portieren und ich dort keine dynamischen Strings verwenden werden (also kein std::string), sondern nur Arrays mit fixer Größe (eben der Fragmentgröße mit ca. 8 KB) wird sich das Problem hoffentlich in den Griff kriegen lassen, da ich bei einem Array mittels Index bei weitem schneller zugreifen kann, als wenn ich bei den dynamischen String die halbe Liste durchgehen muss.

    mfg



  • Possessed schrieb:

    Das Problem daran ist, dass ich es nicht gleich wieder hinausschreiben kann, da ich den komprimierten String wieder als Eingangsstring für den nächsten Schritt brauche, daher kann ich ihn nicht gleich hinausschreiben, sondern muss mir gezwungenermaßen wieder einen neuen String zusammenbasteln und den der nächsten Komprimierungsfunktion vorwerfen.

    Ja du arbeitest halt mit Funktionen, ich habe da eher Streamklassen im Auge 😉

    Possessed schrieb:

    Das Problem an der Größe ist, dass ich im String gewisse Häufigkeiten brauche im überhaupt etwas komprimieren zu können (dieses Argument spricht eher für große Fragmentgrößen), andererseits versuch mal in einem String mit 10.000 Zeichen zu debuggen und das ordentlich nachzuvollziehen (das spricht wiederum für kleinere Fragmente).

    Also bei den ersten 4 Punkten frag ich mich schon warum man KB einlesen muss und nciht byteweise einlesen kann.
    Z.B. Nr.4 läuft ja darauf hinaus, dass du derzeit pro Codewort den ganzen String durchläufst und jedes Vorkommen ersetzt. Wenn man byteweise einfach immer das erste Zeichen umwandelt und direkt rausschreibt läuft das auf ähnlich viele Vergleiche hinaus, aber man verzichtet auf komplexeres entfernen von Elementen.

    VB behandelt Strings afaik auch als Array (kurz gegoogelt).
    Und da ist Einfügen/Entfernen besonderst teuer.

    Falls VB die intern doch nicht als Arrays behandelt würde ich einen Wechsel auf Arrays nicht vornehmen, dann doch lieber etwas schönes mit Pointern, oder ähnlichem basteln 🙂



  • Tellerrand schrieb:

    Ja du arbeitest halt mit Funktionen, ich habe da eher Streamklassen im Auge 😉

    Ich glaube wird reden aneinander vorbei. Konkret weiß ich jetzt nicht was du mit dem Verwenden von Streamklassen anstelle von Funktionen meinst.

    Tellerrand schrieb:

    Also bei den ersten 4 Punkten frag ich mich schon warum man KB einlesen muss und nciht byteweise einlesen kann.
    Z.B. Nr.4 läuft ja darauf hinaus, dass du derzeit pro Codewort den ganzen String durchläufst und jedes Vorkommen ersetzt. Wenn man byteweise einfach immer das erste Zeichen umwandelt und direkt rausschreibt läuft das auf ähnlich viele Vergleiche hinaus, aber man verzichtet auf komplexeres entfernen von Elementen.

    VB behandelt Strings afaik auch als Array (kurz gegoogelt).
    Und da ist Einfügen/Entfernen besonderst teuer.

    Falls VB die intern doch nicht als Arrays behandelt würde ich einen Wechsel auf Arrays nicht vornehmen, dann doch lieber etwas schönes mit Pointern, oder ähnlichem basteln 🙂

    Prinzipiell ist das richtig. Bei Punkt 1 bis 4 könnte ich genausogut byteweise arbeiten, erst bei Schritt 5 brauche ich den ganzen String. Der Nachteil an deinem Vorschlag ist, dass ich dann jedes Byte einzeln an die Funktion übergeben müsste, die Funktion sich jedoch vereinfachen würde, da ich nicht den ganzen String durchgehen müsste sonder immer nur ein Zeichen behandel. Vorteil an meiner Herangehensweise ist, dass ich die Funktion nur einmal aufrufen muss, jedoch in der Funktion dann den gesamte String durchgehen muss. Müsste man probieren was schneller ist (ob jetzt bei einem String von z.B. 1000 Zeichen das durchgehen des gesamten Strings länger dauert oder ob das 1000 mal aufrufen der Funktion mehr Zeit frisst. Ist prinzipiell aber eine gute Vorschlag den ich noch testen werde.

    Wow, sind sie echt Arrays??? 😮 Jetzt bin ich schwer beeindruckt. War mir eigentlich sicher das die in irgendeiner Form Listen sind.

    Pointer! 😡 Ich hasse die Dinger. (Ist noch eine kleine Altlast von mir. Als in der 2. Klasse meiner schulischen Laufbahn der Umstieg vom einsteigerfreundlichen, einfachen VB auf C mit seinen Pointer, Pointern auf Pointern, Adressoperatoren, und, und, und kam, da war ich erstmal a bissl geschockt. Mittlerweile habe ich zwar kein Problem mehr damit, aber jedesmal bei dem Wort muss ich mich daran erinnern.) 😃

    Außerdem weis ich noch immer nicht was du damit meinst einen Teil des Strings während der Funktion "raus zu schreiben". Wenn ich den während der Funktion den String / das Byte in eine Datei schreibe, um ihn gleich danach wieder einzulesen und der nächsten Funktion zu übergeben, würde das 1000 mal länger dauern, als wenn ich den String gleich im Speicher behalte. Aber wie ich oben bereits gesagt habe glaube ich, dass wir da aneinander vorbei reden. Könntest du das vielleicht nocheinmal etwas genauer erklären wie du das meintest?

    mfg



  • Zur Erklärung:

    http://www.galileocomputing.de/openbook/visual_basic/Kapitel_12-004.htm

    2.Pass-Through-Streams ergänzen einen Base-Stream um spezielle Funktionalitäten. So können manche Streams verschlüsselt oder im Hauptspeicher gepuffert werden. Pass-Through-Streams lassen sich hintereinander in Reihe schalten, um so die Fähigkeiten eines Base-Streams zu erweitern. Auf diese Weise lassen sich sogar individuelle Streams konstruieren.

    Das ist halt sowas womit ich basteln würde.
    Dort existiert sogar ein GZipStream.
    Fehlen noch deine Klassen wie WhitespaceEliminatorStream 🤡

    Aber das nun komplett neu zu schreiben wäre viel Arbeit und ich glaube, es liegt wirklich nur an den String Funktionen die du nutzt.
    Wenn es nämlich Arrays sind kann die Rechenleistung duch Einfügen/Entfernen da schnell verloren gehen.

    Mein Vorschlag ist also einfach mal Funktion Nr.4 zu ersetzen.
    In einer Schleife Zeichen für Zeichen analysieren und in einen neuen String die komprimierten Werte reinschreiben. Den neuen String dann weiterreichen. Ist halt die Frage wie man vorher die Größe des neuen Strings abschätzen kann, bzw. was das vergrößern des Strings an Performance kostet.



  • VB ist auch so langsam, ob man nun String Funktionen nutzt oder nicht.
    Wer's ausprobieren will soll einfach mal nen einfachens Apfelmännchen oder sowas in VB und dann in C bzw. C++ programmieren, und dann gucken was schneller ist, und vor allem wieviel.

    Bei VB .NET sieht die Sache wieder etwas besser aus, trotzdem würde ich für sowas (komprimieren) immer C bzw. C++ nehmen und nicht VB - mit oder ohne .NET.



  • kenne mich mit vb nicht aus, kann deshalb nix zur geschwindigkeitsverbesserung sagen. aber der kompressionsgrad könnte vermutlich noch gesteigert werden, wenn vor der rle (schritt 3) noch eine burrows-wheeler-transformation durchgeführt würde.
    zlib sollte außerdem doch auch für vb verfügbar sein und bietet bessere komprimierung als lzw.



  • Possessed schrieb:

    Kleiner Ausblick auf die Zukunft:
    Prinzipiell habe ich vor noch die Huffman-Kodierung einzusetzen, jedoch habe ich bis jetzt im Internet noch nichts Brauchbares gefunden (Naja, ich habe auch noch nicht wirklich intensiv gesucht). Falls ihr eine Bibliothek oder ähnliches kennt in der dieses Verfahren implementiert ist, schreibt mir bitte.

    Wenn du bereits ZIP-Komprimierst, wird dir Huffman nichts mehr bringen: die Bytes, die ZIP ausgibt, sind voellig zufaellig (und in etwa gleichverteilt), aber die Huffman-Kodierung ist nur dann sinnvoll, wenn gewisse Zeichen oefter vorkommen als andere.



  • Blue-Tiger schrieb:

    Possessed schrieb:

    Kleiner Ausblick auf die Zukunft:
    Prinzipiell habe ich vor noch die Huffman-Kodierung einzusetzen, jedoch habe ich bis jetzt im Internet noch nichts Brauchbares gefunden (Naja, ich habe auch noch nicht wirklich intensiv gesucht). Falls ihr eine Bibliothek oder ähnliches kennt in der dieses Verfahren implementiert ist, schreibt mir bitte.

    Wenn du bereits ZIP-Komprimierst, wird dir Huffman nichts mehr bringen: die Bytes, die ZIP ausgibt, sind voellig zufaellig (und in etwa gleichverteilt), aber die Huffman-Kodierung ist nur dann sinnvoll, wenn gewisse Zeichen oefter vorkommen als andere.

    Mir ist schon klar, dass eine LZW-Komprimierung und eine darauffolgende Huffman-Codierung (fast) nichts bringen wirde, da nach dem LZW (wahrscheinlich) nur mehr wenige Häufigkeiten vorhanden sind. Ich habe mich da wohl ein bißchen blöd ausgedrückt. Gemeint habe ich, dass ich prinzipiell beide implementieren möchte um zu prüfen welche der Beiden für meine Zwecke besser geeignet ist.

    @Tellerrand: Danke für deinen Link, war sehr interessant. Bisher habe ich von Streams immer nur im Zusammenhang mit Datein auf der Platte bzw. mit Netzwerk gehört. Das man Streams auch direkt in Hauptspeicher schreiben kann habe ich nicht gewusst.

    @squeeze it!: Ich danke auch dir für deinen Tip! Allerdings, wegen deiner Aussage das es die zlib auch für vb gibt. Ich brauch sie nicht für VB, da es heute jetzt endgültig beschlossen wurde, dass mit einer DLL in C++ zu machen.

    Aber das führt mich gleich zu meiner nächsten Frage:
    Gibt es für die zlib auch irgendwo eine Doku? Der Ersteller schreibt zwar, dass er kein geschrieben hat und empfiehlt den Blick in die Header-Datein, aber ich wollte trotzdem fragen ob vielleicht irgendjemand ein paar Tutorials dazu kennt oder ob jemand anderer vielleicht da einige Sacher überblicksmäßig zusammen geschrieben hat.

    Außerdem hat sich heute wieder ein kleine Änderung ergeben:
    Und zwar wird jetzt die Kompressionsfunktion, die in der DLL ist, immer mit einer Datensatzreihe (d.h. maximal 32.000 Zeichen) aufgerufen. Allerdings, da diese Funktion damit auch ein paar 100.000 Mal aufgerufen wird, wollte ich nocheinmal fragen ob das ein drastischer Performance-Verlust ist, wenn eine Funktion in einer sooft aufgerufen wird?

    Meine letzte Frage:
    Gibt es beim Compiler / Optimieren unterschiede zwischen der Standard und der Express Edition. Besitzte zwar keine Express, würde mich aber trotzdem interessieren. (Ich weiß, dass diese Frage nicht unbedingt hier her gehört, aber ich will nur desswegen keinen eigenen Thread aufmachen!)

    mfg



  • Ich kann dir nur sagen dass die Crypto++ einen fertigen ZLIB und Huffman Encoder/Decoder hat.
    GZIP Encoder/Decoder is auch mit dabei.

    Die Crypto++ ist zwar nicht wahnsinnig gut dokumentiert, dafür baut fast alles auf deren BufferedTransformation Klasse auf. Wenn man das System mal verstanden hat kann man diverse Encoder/Decoder sehr schnell verwenden und auch gegeneinander austauschen.



  • Hm will jetzt nicht deinen ganzen algo über den haufen schmeissen, aber wäre es nicht geschickter (falls die änderungen zwischen den werten in einem gewissen rahmen bleiben) diese direkt als binärzahlen (festkomma) zu kodieren. Wenn du dir am anfang den maximalen größenunterschied anschaust weisst du auch sofort wieviel bytes du maximal für das abspeichern differenzen brauchst und sparst dir so die trennzeichen.
    Danach das ganze (jetzt als string interpretiert) nochmal lzw (evtl burrows wheeler vorher) bzw huffman kodieren.
    Damit sollten einige prozent mehr drin sein.

    bsp 307.22; 309.33 -> 307.22 2.11 -> 01111000 00000010 00000000 11010011 ...

    jeweils 8 Bit bei ASCII oder auch 16 bit bei anderer zeichenkodierung als ein zeichen auffassen. Ergo ohne nachfolgende textkompression hast du aus 14 zeichen 4 gemacht.

    gruss InfoStudKa

    btw was meinst du mit einer kompressionsrate von 90%?



  • Ja, sowas in der Richtung hab ich mir auch schon gedacht. Allerdings müsste ich in den meisten Fällen 2 oder 3 Vorkommazahlen und sicher 2 Nachkommazahlen nehmen, da aber oft Folgen wie 0;0;0;0;0; vorkommen müsste ich das dann in der Festkommadarstellung 00.00 00.00 00.00 00.00 00.00 so speichern (außer den Punkten (Komma), die habe ich nur der Lesbarkeit und dem Verständnis halber gemacht) und dann würde es wieder länger werden.

    Kompressionsrate: Das der String nach der Kompression nur mehr 10% der Länge hat die er vor der Kompression hatte.

    mfg



  • [quote="Possessed"]Hallo!

    Ich schreibe zurzeit ein Komprimierungstool in VB 6.0. Leider ist die Performance von VB, speziell bei großen Dateien (für die das Programm hauptsächlich eingesetzt wird), relativ schlecht.
    Nun habe ich mir gedacht das Tool, zumindest zum Teil, auf C bzw. C++ zu portieren und die Kompressionsfunktion als DLL zu exportieren und in VB zu verwenden, da eine 50MB Datei ca. 20 Tage zum Komprimieren brauchen würde (dafür ist der Kompressionsfaktor hölle 😉 ). Nun meine Fragen:

    1. Wie stark unterscheidet sich C bzw. C++ im Vergleich zu VB6 performancemäßig? Ich will nur einen ungefähren Faktor wissen (z.B.: 2x, 5x, 10x, ... 100000x)!
    2. Wie stark unterscheidet sich C von C++ performancemäßig (da ich relativ laufzeiteffizient arbeiten muss)?
    3. Ist Visual C++ langsamer als "normaler" C/C++ Code der von anderen Compilern kompiliert wurde? Da Visual C++ auf die .NET-Architektur aufsetzt und die meiner Meinung nach relativ überladen und langsam ist?
    4. Wie groß ist der Performanceverlust beim Aufruf einer Funktion in einer DLL? Ich will nämlich (wie oben beschrieben) die Kompressionsalgorithmen in C/C++ schreiben und diese als DLL exportieren und sie dann in VB aufrufen? Das Problem ist, dass ich immer nur 8KB komprimieren kann (d.h. Bei einer 50MB Datei müsste ich die Komprimierungsfunktion (aus der DLL) tausendemale aufrufen. Würde das meinen Geschwindigkeitsvorteil wieder zunichte machen oder ist der Aufruf einer Funktion die in einer DLL ist (laufzeitmäßig) eher unproblematisch?
      test


  • Possessed schrieb:

    Gibt es beim Compiler / Optimieren unterschiede zwischen der Standard und der Express Edition.

    Meines Wissens nicht. VCExpress besitzt die gleiche Compilerversion (cl.exe) wie die reguläre, die Expressversion ist anderweitig eingeschränkt (keine MFC, eine IDE Funktionen fehlen).
    Hier mal Beispiele zum Vergleich:
    VC6SP6

    Optimierender Microsoft (R) 32-Bit C/C++-Compiler, Version 12.00.8804, fuer x86
    Copyright (C) Microsoft Corp 1984-1998. Alle Rechte vorbehalten.
    

    VCEE2008

    Microsoft (R) 32-Bit C/C++-Optimierungscompiler Version 15.00.30729.01 für 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    

    VC2010Prof

    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    


  • Bitte keine Leichenschändung betreiben.



  • hustbaer schrieb:

    std::string verwendet i.A. dynamische Speicheranforderungen (new), um Speicher für den String zu bekommen. MSVC hat AFAIK einen 16 Byte Puffer in std::string eingebaut, d.h. Strings die kleiner als 16 Byte sind sind "schnell". Für alles grössere wird der Speicher vom Heap geholt.

    Finde dazu im Internet nichts, hast du vielleicht eine Quelle?

    Danke.


Anmelden zum Antworten