1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

Array Serialization...?

  • Spite82
  • 31. Oktober 2009 um 08:36
  • Unerledigt
  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 08:36
    • #1

    Hallo, also ich habe es geschafft ein Boolean[,] - (2 dimensionales) Array mit Hilfe eines FileStreams und des BinaryFormatters zu serialisieren. Nun hat aber mein Boolean Array [3600, 1800] Elemente und das serialisieren dauert immer so ca. 10 Sekunden. (was ziemlich viel ist, wie ich finde......). Wie kann man das Beschleunigen, ich mache sowas:

    Code
    FileStream str = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
                BinaryFormatter formatter = new BinaryFormatter();
    
    
                try
                {
                    formatter.Serialize(str, this.allPositions);
                }
                catch (SerializationException)
                {
                }
                finally
                {
                    str.Close();
                }
    Alles anzeigen

    Wobei "this.allPositions" eben das Boolean-Array ist.

    Noch eine Frage, die eher Threading betrifft, aber mit dem serialisieren des Arrays zusammenhängt.

    Ich habe ein Programm geschrieben, in dem mehrere Threads (zZ 32) immer wieder Daten von einer Webseite abfragen. Sind sie mit einem "Gebiet" fertig, dann wird sowas gemacht:

    Code
    if (this.GrabberFinished != null)
                {
                    GrabberFinished(threadIndex);
                    SaveResults(posIndex);
                }

    Dies steht im der, von Thread.Start() aufgerufenen Methode. GrabberFinished ist ein Eventhandler, der nur bei bestimmten Fällen gesetzt ist (daher != null), dann wird das GrabberFinished-Event geworfen, in dem dem aktuellen Thread ein neuer Bereich zugeordnet wird und jetzt wirds spannend: das SaveResults-Event wird geworfen, um die neuen Daten zu speichern (wobei dann eben auch der erste Code-Block aufgerufen wird). Im SaveResults-Eventhandler hab ich dann sowas:

    Code
    if (this.dataGrid.InvokeRequired)
                {
                    IntParamDelegate myDel = new IntParamDelegate(SaveResultsToFile);
                    this.dataGrid.Invoke(myDel, indexDone);
                }
                else
                {
                    Console.WriteLine("Position " + indexDone + " set to true");
                    ///set the Positions bool-value
    
    
                    lock (this)
                    {
                        this.myPositions.positionDone(indexDone);
                        this.myPositions.WritePositionsToFile();
                        this.myStreets.WriteStreetsToFile();
                        Console.WriteLine("Files saved");
                    }
                }
    Alles anzeigen

    Also einfach ein Invoke (wenn notwendig) und sonst eine Textausgabe und dann ein lock mit dem Speicher-Code.

    Und um diesen Lock geht es mir: Da ja 32 Threads gerade mit ihrem Bereich fertig sein können kann dieser Code ja auch 32 mal gleichzeitig aufgerufen werden, auch die "WriteXXXXToFile()-Funktionen - daher der globale Lock.... wie kann man sowas besser machen?? (oder sollte ich einfach einen Counter (zB) einbauen und immer nur nach dem 10. fertigen Bereich einmal schreiben?

    Wie geht sowas elegant?

    Und nochmal zur 1.Frage? Wenn das nicht schneller geht mit der Serialisierung: Sollte ich dann eventuell in Betracht ziehen die BOOLEANs als Bild abzuspeichern? Denn ich bin mir sicher, dass ein Bild recht schnell geladen/gespeichert werden kann, auch in dieser "Auflösung"..... mit OpenGL-Texturen wär das sicher machbar.....

    Lg
    Spite

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 09:14
    • #2

    Noch eine Frage:
    Ich bin nur umgestiegen auf ein Boolean[,], weil ich vorher sowas hatte: List<List<Boolean>> (mit gleich vielen Elementen), nachdem ich aber this.allPositions[x][y] = true gesetzt habe, waren this.allPositions[x][y] == true, sowie auch alle this.allPositions[x + 1][y] == true, this.allPositions[x + 2][y] == true usw, also ALLE mit dem gleichen y-Wert..... woran kann das liegen (diese Variante belegte auch nur ca. 21KB Speicher (waren alles FALSE-Werte am Beginn), meine jetzige Version Boolean[3600, 1800] braucht mehr als 6MB!!!!

    Lg
    Spite

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 10:41
    • #3

    Problem gelöst!

    Auch wenn das schreiben vielleicht beim Serialisieren lange dauert und es schnellere Möglichkeiten gibt (werde mir das ansehen) hab ich ein bisschen umgebaut!

    Nun wird das "SaveResults"-Event nur mehr alle 32 mal, wenn ein Thread fertig ist geworfen. Dann wird im Event-Handler ein neuer "Save-Thread" erstellt und dieser speichert dann die Daten. Das heißt, dass alle anderen Threads weiterlaufen können und somit auch das Programm schneller arbeitet. Es wird jetzt zwar nicht immer der neueste Status (nach jedem Thread-Finish) gespeichert, aber nach ca. 10 Minuten Grabber-Arbeit sind nicht so schlimm, wenn man bedenkt, dass insgesamt ca. 2.592.000.000 WebRequests gestellt werden :) :winking_face:

    Lg
    Spite

  • Wolfibolfi
    37
    Wolfibolfi
    Mitglied
    Reaktionen
    186
    Punkte
    14.936
    Beiträge
    2.942
    • 31. Oktober 2009 um 10:42
    • #4

    Du könntest eventuell noch auf ints umsteigen, und die bits zusammenshiften. Bei so vielen Bools kann das Sinn machen.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 10:52
    • #5

    Danke erstmal für deine Antwort :)

    Keine Ahnung, wie sowas funktioniert..... aber ich bin draufgekommen, dass ein Boolean auch 1 Byte Speicherplatz braucht???? Bei einem "logischen" Speicherplatzbedarf von 1 Bit (0 oder 1)?? Das würde meine Datei auf 1/8 schrumpfen.....

    Ich habe auch mal zum Test die 6MB-Datei gezippt (eigentlich gerart) -> siehe da: 4 Kb !!!!!! Kann man sowas auch mit einem GZippedStream hinbekommen, bzw. wie schnell ist SOWAS??

    Ansonsten klingt das Shiften auch gut, wie funktioniert sowas?

    Lg
    Spite

  • Wolfibolfi
    37
    Wolfibolfi
    Mitglied
    Reaktionen
    186
    Punkte
    14.936
    Beiträge
    2.942
    • 31. Oktober 2009 um 11:09
    • #6

    Der GZippedStream ist wahrscheinlich noch gscheiter.

    Ansonsten: http://www.blackwasp.co.uk/CSharpShiftOperators.aspx

    Oder einfach 8 Bools hernehmen, und je nach dem, obs true oder false ist, die entsprechenden Zweierkomplimente miteinander verodern.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • tdanecker
    3
    tdanecker
    Mitglied
    Reaktionen
    4
    Punkte
    74
    Beiträge
    12
    • 31. Oktober 2009 um 11:34
    • #7

    Versuch doch mal das BitArray, das braucht wirklich nur 1 Bit pro bool

    Fachschaft Informatik

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 14:25
    • #8

    Also ich hab jetzt Beides versucht:
    1. Habe ich, wie hier:
    http://stackoverflow.com/questions/9646…ance-using-gzip
    einen GZipStream verwedet, um mein Boolean[,] Array zu speicher, das resultierte sogar in einer ca. 11MB großen Datei :frowning_face:
    2. Habe ich es auch mit einem BitArray[,] versucht, welches eine genau gleich große Datei, wie bei einem Boolean[,] Array produzierte.....

    Aber das mit dem GZipStream verstehe ich jetzt nicht ganz: Wieso ist das größer und nicht kleiner? Liegt das an dem Binary-Formatter oder am Serialisieren??
    Sollte ich eventuell selbst eine Text-File schreiben und die dann mit einem GZipStream bearbeiten??
    Fragen über Fragen :)

    Lg
    Spite

  • tdanecker
    3
    tdanecker
    Mitglied
    Reaktionen
    4
    Punkte
    74
    Beiträge
    12
    • 31. Oktober 2009 um 14:30
    • #9
    Zitat von Spite82


    2. Habe ich es auch mit einem BitArray[,] versucht


    Das sieht auf den ersten Blick nicht so richtig aus... das wär ja ein zwei-dimensionales Array von BitArrays...
    Entweder du verwendest ein BitArray der größe m x n oder ein Array von BitArrays (BitArray[])...

    Fachschaft Informatik

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 14:41
    • #10

    Thx, so gehts! Danke...... nun schau ich mir noch das mit dem GZipStream an..... wär doch ganz cool das vor dem Schreiben noch zu Zippen.....

    THX und lg
    Spite


    edit:
    yayyyyyyyyyyyyyyy, Also das BitArray in Kombination mit einem GZipStream resultiert in einer 8KB großen Datei (nicht mehr 6MB), sie wird zwar mit der Zeit wachsen, denn am Beginn stehen nur "false" Werte drinnen, aber optimal!!!! THX NOCHMAL!!!

    Einmal editiert, zuletzt von Spite82 (31. Oktober 2009 um 14:45)

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 16:30
    • #11

    Habe ich noch eine Frage (wär ja ZUUUUU schön gewesen :) ).
    Habe jetzt mal testweise das Programm beendet und wollte mal die GZipStream komprimierten, serialisierten Daten laden, aber leider funktioniert das irgendwie nicht....

    Ich verwende die gleiche Methode um eine von mir erstellter Structs in zu speichern. Nach dem Laden der Datei ist die Liste jedoch leer......

    Wie kann man das machen jetzt?

    Ich hab zum lesen der Datei sowas:

    Code
    BinaryFormatter formatter = new BinaryFormatter();
                FileStream fileStr = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Read);
                GZipStream zipStr = new GZipStream(fileStr, CompressionMode.Decompress);
    
    
                try
                {
                    zipStr.Flush();
                    this.allStreets = (List<Street>)formatter.Deserialize(zipStr);
                }
                catch (SerializationException)
                {
                    zipStr.Close();
                    fileStr.Close();
                    WriteStreetsToFile();
                }
                finally
                {
                    zipStr.Close();
                    fileStr.Close();
                }
    Alles anzeigen

    Das zipStr.Flush() is eigentlich nur ein Versuch gewesen..... wie macht man sowas??

    Bitte noch mal um eure Hilfe!

    Lg
    Spite

  • tdanecker
    3
    tdanecker
    Mitglied
    Reaktionen
    4
    Punkte
    74
    Beiträge
    12
    • 31. Oktober 2009 um 16:36
    • #12

    Also, ich würd mal das Flush und den catch-Block entfernen, und auch FileMode.Open verwenden (Create macht nicht wirklich sinn). Falls dann eine Exception fliegt, kannst ja mal schaun was da drinnen steht (oder hier posten :)).

    Fachschaft Informatik

  • Spite82
    8
    Spite82
    Mitglied
    Reaktionen
    1
    Punkte
    571
    Beiträge
    89
    • 31. Oktober 2009 um 16:58
    • #13

    Hmmmmm, also ich habe jetzt:

    Code
    try
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    FileStream fileStr = new FileStream(fileName, FileMode.Open);
                    GZipStream zipStr = new GZipStream(fileStr, CompressionMode.Decompress);
    
    
                    this.allStreets = (List<Street>)formatter.Deserialize(zipStr);
    
    
                    zipStr.Close();
                    fileStr.Close();
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
    
    
                    WriteStreetsToFile();
                }
    Alles anzeigen

    Und jetzt funktioniert es :)

    Optimal :)

    Thx nochmal und lg
    Spite

  • Maximilian Rupp 27. Dezember 2024 um 00:26

    Hat das Thema aus dem Forum Programmieren nach Entwicklung verschoben.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung