Schnellere Funktion als StreamWriter

  • VB.NET

Es gibt 57 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    @fire88 das hab ich ja auch versucht, nur um eine collection in ein array umzuwandeln, das braucht ewig ... es ist übrigens eine collection, weil ein array so unflexibel ist
    @BiedermannS so:

    VB.NET-Quellcode

    1. primes.Clear()
    2. primes.Add(2)
    3. For prime As Integer = 3 max_primes Step 2
    4. teilbar = False
    5. For i As Integer = 2 To Math.Ceiling(prime ^ 0.5)
    6. If prime Mod i = 0 Then
    7. teilbar = True
    8. Exit For
    9. End If
    10. Next
    11. If teilbar = False Then
    12. primes.Add(prime)
    13. End If
    14. Next

    max_primes gibt an, bis zu welcher zahl (einschließlich) nach primzahlen gesucht werden soll
    Drei Worte, die dein Programmieren verändern: Option Strict On

    ich lass das ganze gerade in 2 threads laufen.

    Das ist Thread Nummer 1. Der berechnet nur und schiebt die Zahlen in eine Queue.

    VB.NET-Quellcode

    1. Private Const Zwei As UInt64 = 2
    2. Private Const Vier As UInt64 = 4
    3. Sub start(ByRef callback As Action(Of UInt64), ByRef finished As Action)
    4. _Callback = callback
    5. _finished = finished
    6. Dim t As New Threading.Thread(AddressOf running)
    7. t.Start()
    8. End Sub
    9. Private n As UInt64
    10. Private _Callback As Action(Of UInt64)
    11. Private _finished As Action
    12. Sub running()
    13. _Callback(2)
    14. _Callback(3)
    15. For Me.n = 5 To 100000000 Step 2
    16. Prime()
    17. Next
    18. End Sub
    19. Sub Prime()
    20. If n Mod 2 = 0 OrElse n Mod 3 = 0 OrElse n Mod 7 = 0 OrElse n Mod 5 = 0 Then Exit Sub
    21. Dim r As Double = Math.Sqrt(n), f As UInt64 = 11
    22. If r Mod 1 = 0 Then Exit Sub
    23. While f <= r
    24. If n Mod f = 0 Then Exit Sub
    25. f += Zwei
    26. If n Mod f = 0 Then Exit Sub
    27. f += Vier
    28. End While
    29. _Callback(n)
    30. End Sub
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D
    eventuell währe es schneller in php. das speichern alleine sollte eig. nicht so lange dauern. weil wen du es in ein string ladest und am ende writealltext machst, dan schreibt es alles auf einmal. wen du aber nach jedem schleifendurchlauf schreibst... dan muss er die datei zich mal öffnen schreiben schließen.
    @Fire88: wie erstellst du die Strings bzw. Arrays?

    Strings mit stringbuilder.append?

    Array mit vordefinierten Grenzen? oder jedes mal neu dimensionieren?

    PHP ist eine ScriptSprache für Webanwendungen. O.o

    Wenn man es schnell will, dann c++. Und den stream offen lassen und nicht immer neu öffnen.
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D
    der steht zwar schon am anfang, aber hier nochmal:

    VB.NET-Quellcode

    1. Using sw As New IO.StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) & "\primes.txt")
    2. For i As ULong = 1 To primes.Count
    3. sw.WriteLine(primes(i))
    4. Next
    5. End Using
    6. Console.ForegroundColor = ConsoleColor.Green
    7. Console.WriteLine("File """ & Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) & "\primes.txt"" was successful saved!")
    8. Console.ForegroundColor = ConsoleColor.Gray
    9. My.Computer.Audio.PlaySystemSound(Media.SystemSounds.Asterisk)

    der wird aber nur gestartet, wenn man einen Befehl eingibt, also nicht nach jeder primzahl :D
    Drei Worte, die dein Programmieren verändern: Option Strict On

    FritschFisch schrieb:

    For i As ULong = 1 To primes.Count
    sw.WriteLine(primes(i))
    Next


    Mich wundert dass das nicht abstürzt. Gehört da nicht ein - 1 hin

    VB.NET-Quellcode

    1. For i As ULong = 0 To primes.Count - 1
    2. sw.WriteLine(primes(i))
    3. Next
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D
    mal noch eine idee^^ Ich weiß zwar nicht was ein BuffredStream genau macht - ich vermute aber ähnliches:
    nicht jede Primzahl einzeln speichern, sondern Blockweise. Ein Block könnte z.B. 1000 Primzahlen lang sein... Rechnen geht eben flott - schreiben langsam.

    also immer ca. 1000 (oder noch mehr?) Zahlen in einen Buffer (bytearray) schreiben und erst diesen Buffer per Stream auf die Platte hauen.

    Aber vor allem die Zahlen BINÄR abspeichern! BitConverter-Klasse regelt^^
    Vergleiche mal: 1234567 als string brauch 7byte speicher - binär als integer aber nur 4byte. Jeder Integer braucht eben nur 4Byte. Ein Double immer 8 Byte.
    Vorteil ist außerdem, dass du kein Trennzeichen mehr einzubauen brauchst - du liest blöcke von n-Bytes aus und konvertiertst sie in eine Zahl. Dann kommen die nächsten n-Bytes für die nächste usw

    lg

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

    Zum Thema berechnen ist schneller.

    Bei mir laufen gerade, wie bereits erwähnt, zwei threads. Berechnen und Schreiben.

    Und die Queue die die beiden verbindet, hatte nie mehr wie ein paar Einträge. Je nach dem wie Groß die Zahl bereits ist.

    hier mein Ergebnis:

    Finished in 3194279 ms! (53 Min 14,3 Sec)

    In Wirklichkeit wären es weniger, da ich zwischendurch immer wieder angehalten habe um zu sehen wie weit ich schon bin.

    Das Ergebnis bezieht sich auf das Berechnen aller Primzahlen von 2 bis 100.000.000 und das Schreiben auf die Festplatte. Insgesamt 5761456 Primzahlen.

    Hier mein Code:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public q As New Queue(Of UInt64)
    2. Sub callback(ByVal n As UInt64)
    3. q.Enqueue(n)
    4. End Sub
    5. Private running1 As Boolean = False
    6. Private running2 As Boolean = False
    7. Private stp As New Stopwatch
    8. Sub finished1()
    9. running1 = False
    10. End Sub
    11. Function finished2() As Boolean
    12. If Not running1 And q.Count < 1 Then
    13. running2 = False
    14. stp.Stop()
    15. InputBox("LOL", DefaultResponse:="Finished in " & stp.ElapsedMilliseconds & " ms!")
    16. Return True
    17. Else
    18. Return False
    19. End If
    20. End Function
    21. Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
    22. stp.Start()
    23. Dim c As New Primes
    24. running1 = True
    25. c.start(AddressOf callback, AddressOf finished1)
    26. Dim w As New writer
    27. running2 = True
    28. w.start(q, AddressOf finished2)
    29. End Sub
    30. Class writer
    31. Private sw As New IO.StreamWriter("c:\primes.txt", False, System.Text.Encoding.Default)
    32. Private _finished As Func(Of Boolean)
    33. Private _q As Queue(Of UInt64)
    34. Sub start(ByRef q As Queue(Of UInt64), ByRef finished As Func(Of Boolean))
    35. _q = q
    36. _finished = finished
    37. Dim t As New Threading.Thread(AddressOf run)
    38. t.Start()
    39. End Sub
    40. Sub run()
    41. Do Until _finished()
    42. If _q.Count > 0 Then
    43. sw.WriteLine(_q.Dequeue)
    44. sw.Flush()
    45. End If
    46. Loop
    47. End Sub
    48. End Class
    49. Class Primes
    50. Private Const Zwei As UInt64 = 2
    51. Private Const Vier As UInt64 = 4
    52. Sub start(ByRef callback As Action(Of UInt64), ByRef finished As Action)
    53. _Callback = callback
    54. _finished = finished
    55. Dim t As New Threading.Thread(AddressOf running)
    56. t.Start()
    57. End Sub
    58. Private n As UInt64
    59. Private _Callback As Action(Of UInt64)
    60. Private _finished As Action
    61. Sub running()
    62. _Callback(2)
    63. _Callback(3)
    64. For Me.n = 5 To 100000000 Step 2
    65. Prime()
    66. Next
    67. _finished()
    68. End Sub
    69. Sub Prime()
    70. If n Mod 2 = 0 OrElse n Mod 3 = 0 OrElse n Mod 7 = 0 OrElse n Mod 5 = 0 Then Exit Sub
    71. Dim r As Double = Math.Sqrt(n), f As UInt64 = 11
    72. If r Mod 1 = 0 Then Exit Sub
    73. While f <= r
    74. If n Mod f = 0 Then Exit Sub
    75. f += Zwei
    76. If n Mod f = 0 Then Exit Sub
    77. f += Vier
    78. End While
    79. _Callback(n)
    80. End Sub
    81. End Class

    Ist aber noch nicht zu 100% optimiert.

    Edit:
    @FreakJNS: Binär speichern würde es noch etwas schneller machen.
    und die Klasse für den Writer arbeitet mit einer do loop schleife ohne events, da ließen sich auch noch unnötige aufrufe vermeiden.
    SWYgeW91IGNhbiByZWFkIHRoaXMsIHlvdSdyZSBhIGdlZWsgOkQ=

    Weil einfach, einfach zu einfach ist! :D
    Okay... LOL, also Queue kannte ich noch gar nicht aber scheint eine gute Lösung zu sein, Danke :D
    EDIT:
    Noch eine Frage:
    bei mir findet er nur 5761455 Primzahlen, das ist eine weniger als bei dir. weißt du, woran das liegen könnte?
    Drei Worte, die dein Programmieren verändern: Option Strict On

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