Byte Array möglichst schnell und mit wenig Speicherverbrauch speichern

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Byte Array möglichst schnell und mit wenig Speicherverbrauch speichern

    Ich möchte ein sehr großes Array aus Bytes speichern. Das sollte möglichst schnell ablaufen.

    Eine Möglichkeit ist "Serialize", aber das dauert lange und die Datei wird über einen Gigabyte groß!
    Da das Array im Arbeitsspeicher "nur" ca. 200-300mb verbraucht, muss es ja schließlich zu schaffen sein, das gleich groß in einer Datei abzulegen.

    Mfg

    Edit: Das Array hat 2 Dimensionen

    Crazydrift schrieb:

    Das Array hat 2 Dimensionen

    Wie sind denn die Sizes in beiden Dimensionen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Guck dir mal den BinaryWriter bzw. BinaryReader und FileStream auf MSDNan ;) Das sollte genau das sein, was du brauchst.

    MfG
    Wenn Du Dir eine serialisierbare Klasse bastelst, die ausschließlich dieses Array hält, sollte das bereits die schnellste Möglichkeit sein.
    Mach Dir ein lineares Feld vergleichbarer Größe und vergleich die Save- und Load-Zeit mit dem Serialisieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Wenn Du Dir eine serialisierbare Klasse bastelst, die ausschließlich dieses Array hält, sollte das bereits die schnellste Möglichkeit sein.


    Falsch. Das dürfte um einiges langsamer sein, als das Array einfach direkt per BinaryWriter und einem Stream zu speichern und bringt auch unnötigen Overhead in Bezug auf die Dateigröße mit sich.

    MfG

    Krissel095 schrieb:

    Falsch. Das dürfte ... Dateigröße

    Das Attribut Falsch darfst Du erst dann schreiben, wenn Du den von mir vorgeschlagenen Test durchgeführt hast und hier den Code und die Zeiten posten kannst. :thumbsup:
    Der Oberhead bezüglich Dateigröße ist vernachlässigbar.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    picoflop schrieb:

    Stell um auf eine Dimension und dein Problem ist gelöst
    Korrekt.
    Dann sind auch innerhalb von .NET die Zugriffe mit eigener Indexarithmetik viel schneller, hab ich schon ausprobiert.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Das Attribut Falsch darfst Du erst dann schreiben, wenn Du den von mir vorgeschlagenen Test durchgeführt hast und hier den Code und die Zeiten posten kannst. :thumbsup:

    Kein Problem ;)



    Dateigröße ist wie du bereits sagtest vernachlässigbar, da sie sich bei einem 10000x10000 Array nur um etwa 150KB unterscheidet. Theoretisch müsste er noch die Größe des Arrays mitspeichern, das sind aber nur 2 weitere kleine Aufrufe, durch die nicht sonderlich viel Overhead dazukommen würde.



    MfG
    Wenn man nicht weis, was der Hintergrund ist, braucht man auch keine Vorschläge dazu machen ;)
    Wenn man eine Frage stellt, möchte man doch eine Antwort drauf und nicht wieder tausend Vorschläge drum rum bezüglich Array verkleinern etc. ^^

    @Krissel095
    das speichern hat geklappt, es sind jetzt nur noch knapp ~100mb. Und das in ca 5-10 Sekunden.
    Nun zum auslesen ;)

    MfG

    RodFromGermany schrieb:

    Dann sind auch innerhalb von .NET die Zugriffe mit eigener Indexarithmetik viel schneller, hab ich schon ausprobiert.

    Dann hast du was anderes probiert als ich ... ;)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim d2 As New Simple2DArray(Of Byte)(10000, 10000)
    3. Dim d(9999, 9999) As Byte
    4. Dim dx(10000 * 10000 - 1) As Byte
    5. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    6. End Sub
    7. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    8. Dim stp = Stopwatch.StartNew
    9. For i = 3000 To 4000
    10. For j = 3000 To 4000
    11. d2.Value(i, j) = 1
    12. Next
    13. Next
    14. stp.Stop()
    15. MsgBox(stp.ElapsedTicks)
    16. End Sub
    17. Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    18. Dim stp = Stopwatch.StartNew
    19. For i = 3000 To 4000
    20. For j = 3000 To 4000
    21. d(i, j) = 1
    22. Next
    23. Next
    24. stp.Stop()
    25. MsgBox(stp.ElapsedTicks)
    26. End Sub
    27. Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
    28. Dim stp = Stopwatch.StartNew
    29. For i = 3000 To 4000
    30. For j = 3000 To 4000
    31. dx(i * 10000 + j) = 1
    32. Next
    33. Next
    34. stp.Stop()
    35. MsgBox(stp.ElapsedTicks)
    36. End Sub
    37. End Class
    38. Public Class Simple2DArray(Of T)
    39. Public ReadOnly Data() As T
    40. Private ReadOnly d0 As Integer
    41. Public Sub New(dim1 As Integer, dim2 As Integer)
    42. ReDim Data(dim1 * dim2 - 1)
    43. d0 = dim1
    44. End Sub
    45. Public Property Value(ByVal d1 As Integer, ByVal d2 As Integer) As T
    46. Get
    47. Return Data(d1 * d0 + d2)
    48. End Get
    49. Set(value As T)
    50. Data(d1 * d0 + d2) = value
    51. End Set
    52. End Property
    53. End Class


    Mit der Array Klasse: 10600
    Mit dem einfachen berechnen: 10500
    Mit dem "echten" 2D Array: 9100

    Aber im Normalfall könnte das ggf vernachlässigbar sein (wobei ich persönlich sowieso von einem Fehlansatz beim TE ausgehe)

    Edit: ETC:

    VB.NET-Quellcode

    1. Dim stp = Stopwatch.StartNew
    2. My.Computer.FileSystem.WriteAllBytes("foo.array", d2.Data, False)
    3. stp.Stop()
    4. My.Computer.FileSystem.DeleteFile("foo.array")
    5. MsgBox(stp.ElapsedMilliseconds)
    6. stp = Stopwatch.StartNew
    7. Dim ms As New IO.MemoryStream(d2.Data)
    8. Using fs As New IO.FileStream("foo.array", IO.FileMode.OpenOrCreate)
    9. ms.CopyTo(fs)
    10. ms.Dispose()
    11. End Using
    12. stp.Stop()
    13. MsgBox(stp.ElapsedMilliseconds)


    Writeallbytes = 3 Sekunden
    Stream.Copyto = 0.3 Sekunden

    nuff said ;)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „picoflop“ ()

    picoflop schrieb:

    Dann hast du was anderes probiert als ich ... ;)
    Ich hab meine .NET-Bildverarbeitung sowohl als 2-Dim. als auch als 1-Dim. Array gemacht, und ich hab da einen Standardsatz Operatroren über ein 1024x1024 UShort-Bild je n Mal drüberlaufen lassen, da war das mit dem 1-Dim Array deutlich schneller.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi
    könnte daran liegen, dass die Eigenschaft noch mal Zeit kostet oder wird das vom Compiler wegoptimiert? Der MemoryStream arbeitet intern eigentlich über ein Byte-Array, das er als Puffer verwendet, wenn ich mich richtig daran erinnere, also dürfte er einfach den Puffer per Stream.Write rausschreiben und das wars. An Performanz sollte da also nicht viel rauszuholen sein. Mehrdimensionale Arrays (genauso wie Lower-Bounds-Arrays) sollte man meiner Meinung nach meiden bzw. besser noch gar nicht verwenden. Die passen einfach nicht ins Konzept und werden größtenteils nicht mal anständig unterstützt. Nicht umsonst fliegen dabei die meisten arraybasierten Methoden, die ich bisher getestet habe. Eigentlich wäre da so eine Klasse, wie oben von picoflop aufgezeigt, praktischer, da macht aber der Compiler nicht wirklich mit.

    Gruß
    ~blaze~

    Crazydrift schrieb:

    mit komprimierung die datei von ~120mb auf ~10mb gebracht
    Ja, ZIP kann so was.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!