Seite 7 von 9

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 12:46 pm
von Bebu
Zu deiner Antwort später mehr, muss jetzt in die Arbeit:

Sie dir bitte in TRUNK die hash32.cpp und hash64.cpp die Zeilen 132 bzw. 133

Code: Alles auswählen

it->SetHash( hash );
nochmal an. SetHash() erwartet einen unsigned long long und kein Objekt vom Typ Hash. Den Rest habe ich gefixt.

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 12:51 pm
von cloidnerux
ich sollte aufhören nachts um 3 zu programmieren, da übersehe ich zu viel.
Die Lösung dieses Problems ist einfach: hash.GetHash();

Hab gerade auch keine zeit, Pflicht ruft.

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 10:11 pm
von Bebu
So, jetzt erstmal die versprochene Antwort:
cloidnerux hat geschrieben: Wir erleben hier ein sehr typisches Problem: Mangelnde Kommunikation!
Ich bin verantwortlich für die hashklasse, werde also selber dort Änderungen einführen und Fehler korrigieren.
Wenn du etwas änderst im Trunk und ich davon nichts weiß, kann ich sie auch nicht übernehmen.
Im gegenteil, wie jetzt geschehen habe ich meine neue Version vom branch nach Trunk kopiert.
Ich habe aber in der aktuellen Version alle Fehler beseitigt und die Quellen im Branch sind neu, die habe ich erst vorhin hochgeladen.
Ich Denke, wir sollten uns über einem kürzeren Kommunikationskanal verständigen, sprich ICQ/Skype sonstige Chats und Videokonferenzen.
cloidnerux hat geschrieben: SVN hat extra einen Branch und Trunk. Man soll immer eine Stabile Version im Trunk und alles Instabile und "Work in progress" im branch lassen, das alle die Möglichkeit haben immer eine Funktionierende Version aus dem trunk zu ziehen.
Im gegenteil: du schadest wenn du im Trunk arbeitest! Dadurch das die Dateien im Trunk neuer sind, wird jeder der in seinem Branch weitermachen will auf alte Dateien stoßen, die nur wieder Probleme hervorrufen.
Ich gebe dir teilweise Recht und teilweise auch nicht. Das mit der Kommunikation stimmt, ich habe nicht darauf hingewiesen, dass ich beim Integrieren der Hashklasse Fehler fixen musste.

Achtung hier folgt mein persönliches Verständnis/Meinung zum Thema SVN nach Konsum der vorherrschender Meinung hier im Dedupe Projekt und den SVN Richtlinien: Sobald ein Feature fertig entwickelt ist und nach Trunk wandert, finden kleiner Korrekturen und Verbesserungen, wie z. B. das Hinzufügen einer Funktion in Trunk statt, vor allem wenn es sich um Fixes handelt, die in anderen Teilen des Projektes benötigt werden. Wenn jemand dann in seinem Branch weiterentwickeln will, muss er selber darauf achten, das Trunk und Branch nicht zu weit auseinanderdriften und inkompatibel werden, sprich er muss Trunk regelmäßig auf den Branch mergen, damit er mit dem aktuellen Stand arbeiten kann, weil sich zum Beispiel Klasseninterfaces verändert haben.

Damit zum aktuellen "Problemfall": Die Entwicklung der Hashklasse war vor Monaten abgeschlossen und dementsprechend hast du sie völlig korrekt nach Trunk kopiert. Damit ist der Branch eigentlich tot, er hat seinen Zweck erfüllt. Da Hash jetzt im Trunk liegt, kann jeder daran arbeiten und Verbesserungen vornehmen. Mir sind nach der Integration einige kleine Fehler im Codingstandard aufgefallen und habe angefangen sie zu korrigieren, lediglich optische Verbesserungen, keine große Sache. Einige Zeit später habe ich festgestellt, das für die Hashklasse eine Zusatz nötig war, damit sie sich ordentlich mit den anderen Modulen verwenden lässt und habe dich in der Hinsicht um Rat gefragt( Du erinnerst dich bestimmt an unseren PN Austausch zu dem Thema ). Du hast das Problem sehr schnell angegangen und die entsprechende Funktion hinzugefügt und zwar auf der Grundlage des Dateistandes in deinem Branch. Vor zwei Tagen habe ich jetzt die Zeit gefunden, deine Zusatzfunktion anzusehen und sie von deinem Branch nach Trunk kopiert. Dabei habe ich festgestellt, dass die Dateien neben ein paar kleinen vertippern und kleinen Fehlern auch noch auf das veraltete Interface von Filesearch zurückgreift. Also habe ich die Sachen so gefixt, das der Code kompiliert. Als Folge davon sind jetzt die Verbesserungen im Codestandard verloren, was ich jetzt nicht so sonderlich schlimm finde und ich hatte eine Stunde Sucharbeit, um den Code überhaupt zum kompilieren zu bekommen. Beim herumspielen habe ich den vorhin erwähnten Bug entdeckt und dich auf den Bug hingewiesen. Um dir die Fehlersuche zu erleichtern, habe ich diesen Stand nach Trunk hochgeladen, da Trunk der Hauptzweig ist und ich derzeit ausschließlich dort arbeite. Solange die eigene Arbeit nicht die Arbeit der anderen stört, z.B. weil es riesige Umbauten gibt und laufend der Build bricht, ist das auch vollig legitim und normal, zumal wir noch nicht einmal so weit sind, eine Alpha zu veröffentlichen. Stablile Releaseversionen wandern ohnehin nach Tag, Trunk verändert sich also laufend. Darauf hast du den Fehler gefixt und zwar wieder in dem Hash Branch und das ganze dann ohne weiter Nachfrage nach Trunk kopiert. Damit sind alle schon gefixten Fehler wieder da und ich musste den Code nochmal anpassen.

Ich finde folgenden zwei Punkte dabei nicht in Ordnung:
Zum einen, dass du Fehlerkorrekturen in einen Branch commitest, der noch nie mit Trunk gemerged wurde, bzw. nicht auf dem aktuellen Stand ist und eigentlich schon seit bestimmt schon fast 6 Monaten tot ist.
Zum anderen finde ich es falsch, Code nach Trunk zu kopieren, der noch nicht einmal durch den eigenen Compiler gelaufen ist und folglich eine Menge Fehler enthalten kann und sie wie aktuell zu sehen, auch enthalten hat.

Ich mache darum den Vorschlag, solche Fehler entweder in Trunk direkt zu fixen, bzw. sich daraus eine aktuelle Arbeitskopie zu erstellen, den Fehler da zu fixen, das ganze testweise kompilieren zu lassen und dann zu commiten. Die andere Lösung wäre es, Trunk auf den eigenen Branch zu mergen und dann dort die Fehler zu fixen. Wenn man selber nicht kompilieren kann, können auf der Grundlage die anderen Testen und Rückmeldung geben. Wenn alles in Ordung ist, kann man das ganze nach Trunk reintegrieren. Diese Vorgehen kostet nicht viel Zeit, ist einfach und dadurch hätten wir allen Problemen aus dem Weg gehen können.

Bitte werte das nicht als persönlichen Angriff, ich hoffe der Ton ist sachlich und nicht beleidigend, das war nie meine Absicht.

So jetzt wieder zu dem Bug
cloidnerux hat geschrieben: Die Lösung dieses Problems ist einfach: hash.GetHash();
Als erstes: Trunk enthält momentan die aktuellste Version. Der Code kompiliert, allerdings erhalte ich jetzt statt eines bad_alloc Fehlers bei sehr großen Dateien ein Segmentation fault. Kleine Dateien werden problemlos gehasht, ab 6 GB aufwärts Segmentation fault. Da ich vier GB Ram und 2 GB Swap habe, vermute ich mal, das der Ram noch immer überläuft.

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 10:35 pm
von cloidnerux
Es war ein Fehler auf beiden Seiten und viel Ignoranz von mir, da ich nicht einmal in der History nachgeschaut habe.
Der Fehler entstand aber auch nur, weil das ganze zu einem Recht Instabilen System wurde, weil hauptsächlich du daran Arbeitest, also du auch genau weißt wie alles ist und deswegen nichts Zerstörst. Da ich aber dies nicht wusste, ist das System Teilweise Kollabiert.
Ein weiteres Problem ist, dass ich den Code noch gar nicht testen Konnte, weil ich noch nicht die zeit fand, alle bindings zu Installieren und zu testen. Zudem gab mir die Mixtur aus Code vom branch und trunk haufenweise Fehler, jetzt weiß ich ja wodran es liegt.
Achtung hier folgt mein persönliches Verständnis/Meinung zum Thema SVN nach Konsum der vorherrschender Meinung hier im Dedupe Projekt und den SVN Richtlinien: Sobald ein Feature fertig entwickelt ist und nach Trunk wandert, finden kleiner Korrekturen und Verbesserungen, wie z. B. das Hinzufügen einer Funktion in Trunk statt, vor allem wenn es sich um Fixes handelt, die in anderen Teilen des Projektes benötigt werden. Wenn jemand dann in seinem Branch weiterentwickeln will, muss er selber darauf achten, das Trunk und Branch nicht zu weit auseinanderdriften und inkompatibel werden, sprich er muss Trunk regelmäßig auf den Branch mergen, damit er mit dem aktuellen Stand arbeiten kann, weil sich zum Beispiel Klasseninterfaces verändert haben.
Wir wollen das hier nicht zu einer Grundsatzdiskussion zu Softwareplanung und dem Einsatz von Versionsmanagement Systemen werden lassen.
Es ist schon sinnvoll, wenn branch Aktueller ist als trunk, aber nur wenn man mehr als 2 Entwickler hat, aber das ein ander mal.
Bitte werte das nicht als persönlichen Angriff, ich hoffe der Ton ist sachlich und nicht beleidigend, das war nie meine Absicht.
Wer Argumentiert, beleidigt nicht. Auch hast du es als persönliche Meinung gekennzeichnet und als solche muss ich sie Akzeptieren.
Und ehrlich gesagt habe ich besseres zu tun, als über denn Sinn und Unsinn des ganzen zu Diskutieren ;)
Kleine Dateien werden problemlos gehasht, ab 6 GB aufwärts Segmentation fault. Da ich vier GB Ram und 2 GB Swap habe, vermute ich mal, das der Ram noch immer überläuft.
So wie das Konzept des Algorithmus jetzt ist, wird 100MB ram angefordert, es werden 100MB oder eben bis zum Ende der Datei gelesen und dann sequenziell gehasht.
Am besten wird erstmal das

Code: Alles auswählen

int length
gegen ein

Code: Alles auswählen

unsigned long long int length
ausgetauscht, damit nicht bei 2GB Schluss ist, noch so ein Dämlicher Fehler.
Dann müsste man mal ausprobieren, das

Code: Alles auswählen

delete data;
hinter die for-schleife zu ziehen. Nutzt du den 32 oder 64-Bit Hash?

MfG cloidnerux.

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 10:56 pm
von Bebu
cloidnerux hat geschrieben:Es war ein Fehler auf beiden Seiten und viel Ignoranz von mir, da ich nicht einmal in der History nachgeschaut habe.
Der Fehler entstand aber auch nur, weil das ganze zu einem Recht Instabilen System wurde, weil hauptsächlich du daran Arbeitest, also du auch genau weißt wie alles ist und deswegen nichts Zerstörst. Da ich aber dies nicht wusste, ist das System Teilweise Kollabiert.
Ein weiteres Problem ist, dass ich den Code noch gar nicht testen Konnte, weil ich noch nicht die zeit fand, alle bindings zu Installieren und zu testen. Zudem gab mir die Mixtur aus Code vom branch und trunk haufenweise Fehler, jetzt weiß ich ja wodran es liegt.
Ich kann dir meine Skype-Adresse anbieten, dann könne wir uns da in Zukunft schneller kurz schließen und solche Probleme von vornherein vermeiden.
cloidnerux hat geschrieben: Und ehrlich gesagt habe ich besseres zu tun, als über denn Sinn und Unsinn des ganzen zu Diskutieren ;)
Dann sind wir schon zwei, so ellenlange Texte zu schreiben kostet ganz schön viel Zeit ;)
cloidnerux hat geschrieben: So wie das Konzept des Algorithmus jetzt ist, wird 100MB ram angefordert, es werden 100MB oder eben bis zum Ende der Datei gelesen und dann sequenziell gehasht.
Am besten wird erstmal das

Code: Alles auswählen

int length
gegen ein

Code: Alles auswählen

unsigned long long int length
ausgetauscht, damit nicht bei 2GB Schluss ist, noch so ein Dämlicher Fehler.
Dann müsste man mal ausprobieren, das

Code: Alles auswählen

delete data;
hinter die for-schleife zu ziehen. Nutzt du den 32 oder 64-Bit Hash?
Ich werde das mal lokal an der Arbeitskopie ausprobieren. Ich nutze den 64 bit Hash

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 11:04 pm
von cloidnerux
Ich kann dir meine Skype-Adresse anbieten, dann könne wir uns da in Zukunft schneller kurz schließen und solche Probleme von vornherein vermeiden.
Ich hab dir schnell meinen Namen geschickt, damit wir das Problem schnellstmöglich vom Tisch haben.
Dann sind wir schon zwei, so ellenlange Texte zu schreiben kostet ganz schön viel Zeit
Und mich kostet es viel zeit sie zu Lesen^^
Ich werde das mal lokal an der Arbeitskopie ausprobieren. Ich nutze den 64 bit Hash
Dann schaue ich mir das mal genauer an.

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 11:29 pm
von fat-lobyte
Damit zum aktuellen "Problemfall": Die Entwicklung der Hashklasse war vor Monaten abgeschlossen und dementsprechend hast du sie völlig korrekt nach Trunk kopiert. Damit ist der Branch eigentlich tot, er hat seinen Zweck erfüllt.
Sollte ich die SVN doku richtig verstanden habe, ist das auch übliche Praxis. Branches sind noch dazu tatsächlich tot und können (ohne irgendwelche spielereien mit svnprops) rein technisch nicht mehr nach zurückgemerget werden.[/quote]
cloidnerux hat geschrieben:Es war ein Fehler auf beiden Seiten und viel Ignoranz von mir, da ich nicht einmal in der History nachgeschaut habe.
Der Fehler entstand aber auch nur, weil das ganze zu einem Recht Instabilen System wurde, weil hauptsächlich du daran Arbeitest, also du auch genau weißt wie alles ist und deswegen nichts Zerstörst. Da ich aber dies nicht wusste, ist das System Teilweise Kollabiert.
Ein weiteres Problem ist, dass ich den Code noch gar nicht testen Konnte, weil ich noch nicht die zeit fand, alle bindings zu Installieren und zu testen. Zudem gab mir die Mixtur aus
Code vom branch und trunk haufenweise Fehler, jetzt weiß ich ja wodran es liegt.
Ich finde gerade am Anfang ist es wichtig den Fokus darauf zu legen dass das ding erstmal kompiliert. Ich habs in den letzten Monaten ein paar mal mit svn up && cmake && make versucht, aber so einfach gehts leider noch nicht.
Wir wollen das hier nicht zu einer Grundsatzdiskussion zu Softwareplanung und dem Einsatz von Versionsmanagement Systemen werden lassen.
Warum eigentlich nicht? Gehört auch geregelt und geklärt.

Am besten wird erstmal das

Code: Alles auswählen

int length
gegen ein

Code: Alles auswählen

unsigned long long int length
ausgetauscht, damit nicht bei 2GB Schluss ist, noch so ein Dämlicher Fehler.
So einfach ist das leider nicht. Erstens ist long long int nicht in C++03-Standard enthalten, sondern nur in C99 oder C++0x. Es funktioniert auf dem GCC zwar als erweiterung, aber "echtes C++" ist das nicht.

Zweitens wirds bei großen Dateien mit der Standardbibliothek schwierig.
Ich glaube hier musst man einfach die bittere Pille schlucken und akzeptieren dass es ohne #ifdef's nicht geht. Dazu ein paar Links zur Anregung:
http://learn-from-the-guru.blogspot.com ... or-cc.html
http://en.wikipedia.org/wiki/Large_file_support
http://ac-archive.sourceforge.net/largefile/glibc.html
http://linux.derkeiler.com/Newsgroups/c ... 00983.html

Um große Dateien effektiv in den Speicher zu laden würde ich zu memory mapped files raten:
http://en.wikipedia.org/wiki/Mmap
http://msdn.microsoft.com/en-us/library ... h09_topic5
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Mehr weiß ich dazu leider auch nicht.
Dann müsste man mal ausprobieren, das

Code: Alles auswählen

delete data;
hinter die for-schleife zu ziehen. Nutzt du den 32 oder 64-Bit Hash?
Ja hoffentlich, man kann doch speicher mehrmals benutzen, oder nutzt der sich ab? ;-)

Re: Hashfunktion

Verfasst: Fr Jul 15, 2011 11:49 pm
von cloidnerux
Ich finde gerade am Anfang ist es wichtig den Fokus darauf zu legen dass das ding erstmal kompiliert. Ich habs in den letzten Monaten ein paar mal mit svn up && cmake && make versucht, aber so einfach gehts leider noch nicht.
Wenn man tools wie SVN einsetz, muss man es auch Konsequent nutzen. Es ist aber gängige Praxis, das nach 5 tagen alles per MBIC(Management by infiniete chaos) geregelt wird.
Warum eigentlich nicht? Gehört auch geregelt und geklärt.
Gehört es auch, aber nicht in diesem Thread.
So einfach ist das leider nicht. Erstens ist long long int nicht in C++03-Standard enthalten, sondern nur in C99 oder C++0x. Es funktioniert auf dem GCC zwar als erweiterung, aber "echtes C++" ist das nicht.
Wäre ja auch fast zu schön :D
Aber es "fixt" erstmal das Problem und ich/wir können und eine bessere Lösung ausdenken.
Zweitens wirds bei großen Dateien mit der Standardbibliothek schwierig.
Ich glaube hier musst man einfach die bittere Pille schlucken und akzeptieren dass es ohne #ifdef's nicht geht. Dazu ein paar Links zur Anregung:
Dann muss ich mir in der nächsten zeit wohl etwas Freiraum schaffen und Kaffee kochen^^
Ja hoffentlich, man kann doch speicher mehrmals benutzen, oder nutzt der sich ab?
Ok, mir fällt auch der geniale Denkfehler des ganzen auf: es wird ja weiterhin Speicher angefordert *kopf->tisch*
Meine Idee war egt, das das OS nicht schnell genug im Befreien des Rams durch delte wäre, sodass immer mehr freie Speicher alloziert wird, bis dann einmal Feierabend ist....



Ok, fassen wir zusammen:
Wir werden mit großen Dateien auf Probleme stoßen, die behoben werden müssen, bevor sie uns aufhalten.
Mögliche Lösungen sind mmap oder Spezielle Compiler-Flags.
Dann müssen wir die Performance anziehen, bebu brauchte für nen 28 GB hash 10min, was aber zu erwarten ist.
Grundsätzlich gibt es 2 Flaschenhälse: Die HDD und die iterative Abarbeitung des ganzen.
Das Problem mit der HDD ist erstmal am größten, denn was sie nicht mehr hergibt, können wir auch durch Parallelisierung nicht rausholen, im gegenteil, hashen wir mehrere Dateien gleichzeitig kann es passieren, das die HDD immer zwischen verschiedenen Spuren hin und her wechselt und so viel zeit verschwendet, was alles noch Verlangsamt.
Dadurch das immer gewartet wird bis eine Datei fertig gehasht ist, verschwenden wir egt Zeit. Mit einem Intelligenten Algorithmus könnte man in der zeit wo eine Datei hasht Daten auslesen und dann Wechseln, was aber einen Intelligenten Supervisor verlangt und sicherstellen muss, das wir nichts durcheinander werfen.
Was aber auf jeden Fall parallelisiert werden kann, sind Dateizugriffe auf verschiedene Datenträger, da wir ja nicht alles durch 1 Bus quetschen müssen. Problematisch wird das mit Partitionen.

Alles in allem: nix was man mit Kaffee und Zeit nicht lösen könnte^^

MfG cloidnerux.

Re: Hashfunktion

Verfasst: Sa Jul 16, 2011 11:32 am
von Bebu
fat-lobyte hat geschrieben: So einfach ist das leider nicht. Erstens ist long long int nicht in C++03-Standard enthalten, sondern nur in C99 oder C++0x. Es funktioniert auf dem GCC zwar als erweiterung, aber "echtes C++" ist das nicht.

Zweitens wirds bei großen Dateien mit der Standardbibliothek schwierig.
Ich glaube hier musst man einfach die bittere Pille schlucken und akzeptieren dass es ohne #ifdef's nicht geht.
Bei welchen Compilern, bzw. Systemen werden wir mit long long int auf Probleme stoßen?

Wie groß muss die Ausgangsdatei sein, damit sie Schwierigkeiten macht?

Re: Hashfunktion

Verfasst: Sa Jul 16, 2011 1:03 pm
von fat-lobyte
Bebu hat geschrieben:Wie groß muss die Ausgangsdatei sein, damit sie Schwierigkeiten macht?
Wenn, dann an der 2 GB Grenze, da viele Funktionen der C-Bibliothek noch int's als Größenvariablen verwenden.
Bebu hat geschrieben:Bei welchen Compilern, bzw. Systemen werden wir mit long long int auf Probleme stoßen?
Gute Frage. Ich glaube das Hauptproblem sind eben die auf manchen Systemen zu kleinen Variablen. Ich habe hier mal ein kleines Testprogramm geschrieben, das auf verschiedenen Systemen (Windows, Linux, Mac, 64 bit und vor allem 32 bit!) ausgeführt werden sollte um mal zu schauen wie das System auf große dateien reagiert:

Code: Alles auswählen

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>

int main(int argc, char* argv[])
{
    std::cout<<
        "sizeof(int) = "<<sizeof(int)<<'\n'<<
        "sizeof(long int) = "<<sizeof(long int)<<'\n'
        <<std::endl;



    if (argc != 2) 
    {
        std::cerr<<"Expecting filename as an argument.\n";
        return 1;
    }

    FILE* file_fstruct =  fopen(argv[1], "r");
    if (file_fstruct == NULL)
    {
        perror("fopen()");
    }
    else
    {
        // seek to the end
        fseek(file_fstruct, 0, SEEK_END);
        long int siz = ftell(file_fstruct);
        if (siz == -1L)
            perror("ftell()");
        else
            std::cout<<"Filesize appears to be "<<siz<<" ("<< (siz >> 30) <<" GB)\n";

        // seek to 2GB boundary,
        int two_GB_boundary = 0x7FFFFFFF;
        int ret = fseek(file_fstruct, two_GB_boundary, SEEK_SET);
        if (ret)
            perror("fseek() to 2 GB");
        else
        {
            int data_buffer[4];

            // now try to read past the 2 gigs boundary
            size_t el_read = fread(data_buffer, sizeof(int), 4, file_fstruct);
            if (el_read != 4)
                perror("fread() after 2 GB boundary failed");
            else
                std::cout<<"fread() after 2 GB boundary succeeded\n";
        }

        // seek to 4GB boundary,
        int four_GB_boundary = 0xFFFFFFFF;
        ret = fseek(file_fstruct, four_GB_boundary, SEEK_SET);
        if (ret)
            perror("fseek() to 4 GB");
        else
        {
            int data_buffer[4];

            // now try to read past the 4 gigs boundary
            size_t el_read = fread(data_buffer, sizeof(int), 4, file_fstruct);
            if (el_read != 4)
                perror("fread() after 4 GB boundary failed");
            else
                std::cout<<"fread() after 4 GB boundary succeeded.\n";
        }

        fclose(file_fstruct);
    }


    return 0;
}
Das ist mein System:
OS: Linux 2.6.38, 64 bit
Compiler: gcc 4.6
glibc: 2.14
Und das ist die Ausgabe:

Code: Alles auswählen

./largefile /media/4EBC5FB82435B0EE/isos/einegrossedatei.iso 
sizeof(int) = 4
sizeof(long int) = 8

Filesize appears to be 7084402688 (6 GB)
fread() after 2 GB boundary succeeded
fread() after 4 GB boundary succeeded