Threading zur Speed Optimierung

  • VB.NET

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Psike2k11.

    Threading zur Speed Optimierung

    Hi nachdem ich jetzt sicher verschlüsseln kann ist mir aufgefallen das bei meiner Methode sehr viel zeit verloren geht, also dachte ich mir ich könnte das verschlüsseln der felder in einzelne threads packen
    Bitte schaut euch meinen Code an an der stelle im switch würde ich gerne wo aktuell alle verschlüsselungen nacheinander laufen parralel und am ende alles wieder in der Zeile ausgeben und so weiter!

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.IO
    3. Public Class cl_csv
    4. Shared Sub csvtoarray2(ByVal datapath As String, ByVal key As String, ByVal crypt As Integer, ByVal kind As Integer)
    5. Try
    6. Dim status As String = 0
    7. ' fileNameIn ermitteln, hier im Beispiel nicht per OpenFileDialog
    8. Dim fileNameIn As String = datapath
    9. Dim fileNameOut As String = fileNameIn & "_NEW.csv"
    10. ' streamReader, streamWriter definieren und öffnen
    11. Dim reader As New IO.StreamReader(fileNameIn)
    12. Dim writer As New IO.StreamWriter(fileNameOut, False)
    13. ' zeilenweise lesen
    14. While reader.Peek <> -1
    15. ' zeile lesen:
    16. Dim lineIn As String = reader.ReadLine
    17. ' in ein array splitten:
    18. Dim args() As String = lineIn.Split(";")
    19. ' Headlines Yes/no?
    20. If fm_main.headline = False Then
    21. ' Auswahl bestand oder schaden!
    22. ' Encrypt Strings you want
    23. Select Case kind
    24. Case 0 ' Bestand
    25. Select Case crypt
    26. Case 0
    27. Dim cCrypt As cCrypt = New cCrypt
    28. cCrypt.Encrypt(128, args(3).ToString, key)
    29. args(3) = cCrypt.EncryptedString
    30. Case 1
    31. Dim cCrypt As cCrypt = New cCrypt
    32. cCrypt.Decrypt(128, args(3).ToString, key)
    33. args(3) = cCrypt.DecryptedString
    34. End Select
    35. Case 1 ' Schaden
    36. Select Case crypt
    37. Case 0
    38. Dim cCrypt As cCrypt = New cCrypt
    39. cCrypt.Encrypt(128, args(0).ToString, key)
    40. args(0) = cCrypt.EncryptedString
    41. cCrypt.Encrypt(128, args(2).ToString, key)
    42. args(2) = cCrypt.EncryptedString
    43. cCrypt.Encrypt(128, args(3).ToString, key)
    44. args(3) = cCrypt.EncryptedString
    45. cCrypt.Encrypt(128, args(5).ToString, key)
    46. args(5) = cCrypt.EncryptedString
    47. Case 1
    48. Dim cCrypt As cCrypt = New cCrypt
    49. cCrypt.Decrypt(128, args(0).ToString, key)
    50. args(0) = cCrypt.DecryptedString
    51. cCrypt.Decrypt(128, args(2).ToString, key)
    52. args(2) = cCrypt.DecryptedString
    53. cCrypt.Decrypt(128, args(3).ToString, key)
    54. args(3) = cCrypt.DecryptedString
    55. cCrypt.Decrypt(128, args(5).ToString, key)
    56. args(5) = cCrypt.DecryptedString
    57. End Select
    58. End Select
    59. End If
    60. ' neue Zeile ergänzen und schreiben
    61. Dim lineOut As String = ""
    62. For i = 0 To args.Length - 1
    63. lineOut = lineOut + args(i) + ";"
    64. fm_main.pb_status.Value = i + 1
    65. fm_main.pb_status.Refresh()
    66. Next
    67. writer.WriteLine(lineOut)
    68. Console.WriteLine(lineOut)
    69. fm_main.headline = False
    70. status = status + 1
    71. fm_main.lb_status.Text = status
    72. fm_main.lb_status.Refresh()
    73. End While
    74. ' reader und writer sauber schliessen
    75. reader.Close()
    76. writer.Close()
    77. fm_main.pb_status.Visible = False
    78. MsgBox("Operation Done", MsgBoxStyle.OkOnly)
    79. ' falls gewünscht weitere File Operationen zum löschen der alten und umbenennen der neuen Datei
    80. If fm_main.cb_mode.Checked = True Then
    81. IO.File.Delete(fileNameIn)
    82. IO.File.Move(fileNameOut, fileNameIn)
    83. End If
    84. Catch E As Exception
    85. ' Let the user know what went wrong.
    86. MsgBox(E.Message, MsgBoxStyle.OkOnly)
    87. End Try
    88. End Sub
    89. End Class


    danke fürs Lesen!

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    ...mal eine frage am rande, für was entschlüsselst du einzelne datensätze, mach dir spaß bei öffnen jeden Datensatz password einzugeben ?
    Wie wärs wenn du einfach alle Datensätze verschlüsselst und beim öffnen deine Anwendung gibst du nur ein mal password und dann kannst
    deine Datensätze verwalten, bearbeiten usw...beim schliesen Anwendung Daten speichern und Verschlüsseln, Verschlüsseln kannst in separaten Thread ausführen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „SystemUnknow“ ()

    richtig viel ist da mit threading nicht zu holen. naja, immerhin würde 2 Threads 2 kernels ausnutzen.

    mehr threads bringen nix, denn jeder Thread kriegt ja nur einen Anteil der insgesamt verfügbaren CPU-Power, und ob nun ein thread mit 100% arbeitet oder 5 Threads mit je 20% - kommt fast aufs selbe raus, ausser, dass bei 5 Threads noch einiges an Leistung für die Thread-Verwaltung draufgeht.

    vlt. hat dein verschlüsselungs-Algo Optimierungs-Potential.

    nebenbei: Welche Funktion erfüllt das .ToString bei args(0).ToString ?

    Edit: @systemUnknown: das ist schon nicht ganz sinnlos, erklärt isses hier: [VB 2010] String Verschlüssen/Entschlüsseln mit Key - aber den Thread kennsteja.

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

    ErfinderDesRades schrieb:

    vlt. hat dein verschlüsselungs-Algo Optimierungs-Potential.

    Ich würde mal sagen der ganze Code hat vermutlich noch viel Potential ;)

    Es ist ja immer noch nicht geklärt, WARUM überhaupt "verschlüsselt" werden muss.
    Normalerweise würde es völlig reichen, die relevanten Daten als Index/Referenz auf eine Datei/Datenbank zu speichern, die das aus eben NICHT verläßt. Dadurch kann inhouse mit den korrekten Daten gearbeitet werden und externe Dienstleisten bekommen nur bedeutungslose Zahlen geliefert. Dieses Verfahren würde vermutlich schon mal 90%+ Rechenzeit sparen ;)
    Jepp - in die Richtung ging auch eine meiner überlegungen:

    ErfinderDesRades schrieb:

    Auch eine Überlegung wäre, ob man die 50 Spalten, die den Fremdabrechner nix angehen, ob man die nicht lieber gleich ganz entfernt. Statt der Kundennummer könnte man eine IndexNummer dranmachen, anhand der man das Elaborat dann wieder zuordnet.

    Oder man lässt die Kunden nummer sogar drin und unverschlüsselt. Was nützt es dem Fremdabrechner ohne die anneren 49 Spalten ?

    ErfinderDesRades schrieb:

    nebenbei: Welche Funktion erfüllt das .ToString bei args(0).ToString ?
    Die funktion erwartet einen string wenn ich ihm die stellle im Array mitgebe sagt der debugger mir das er ein String erwartet und kein Array....

    Also das Problem ist folgendest die datenbank ist einfach ohne konzept erweitert worden hat inzwischen 500 felder und davon weiss man nicht mal wofür diese sind, was wir aber haben ist ein report der als csv exportiert wird der schon vor jahren erstellt wurde und genau das beinhaltet was wir brauchen, deswegen muss ich in einer csv verschlüsseln...
    ich habe mir das ganze mal beim durchlaufen der Datensätze angesehen die Auslastung liegt bei 10% also dachte ich mir warum nicht 5 mal 10% um die speed zu verfünffachen....

    Meinen Verschlüsselungsalgoritmus:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Security.Cryptography
    3. Public Class cCrypt
    4. #Region "Zustandsvariablen"
    5. Private EncryptedString_ As String
    6. Private DecryptedString_ As String
    7. #End Region
    8. Public Sub New()
    9. End Sub
    10. #Region "Methoden"
    11. ' Verschlüsseln
    12. Public Sub Encrypt(ByVal AESKeySize As Int32, _
    13. ByVal DecryptedString As String, _
    14. ByVal Password As String)
    15. ' Der Salt-Wert ist eine zufällig gewählte Zeichenfolge,
    16. ' wenn man so will ein zweites Passwort.
    17. ' Nur wer den Salt-Wert und das Passwort kennt,
    18. ' kann entschlüsseln.
    19. ' Durch Verwendung eines Salt-Wertes ist es deutlich
    20. ' schwerer das Passwort zu knacken.
    21. ' Wird das Passwort selber zur Erstellung des Salt-Wertes
    22. ' verwendet, muss dieses mindestens 8 Zeichen haben.
    23. Dim Salt() As Byte
    24. Salt = System.Text.Encoding.UTF8.GetBytes( _
    25. "123456789")
    26. ' Mit Hilfe des Passwortes und des Salt wird ein Key (Hash-Wert)
    27. ' generiert, der später zur Initialisierung des
    28. ' AES-Algorithmus verwendt wird.
    29. Dim GenerierterKey As New Rfc2898DeriveBytes(Password, Salt)
    30. ' Instanzierung des AES-Algorithmus-Objekts mit 256-bit
    31. ' oder 128-bit Schlüssel und 128-bit Block-Size
    32. Dim AES As New AesManaged
    33. AES.KeySize = AESKeySize ' möglich sind 256 oder 128 bit
    34. AES.BlockSize = 128
    35. ' Algorithmus initialisieren:
    36. AES.Key = GenerierterKey.GetBytes(AES.KeySize \ 8)
    37. AES.IV = GenerierterKey.GetBytes(AES.BlockSize \ 8)
    38. ' Memory-Stream und Crypto-Stream erzeugen -> CreateEncryptor()
    39. Dim ms As New IO.MemoryStream
    40. Dim cs As New CryptoStream(ms, AES.CreateEncryptor(), _
    41. CryptoStreamMode.Write)
    42. ' Daten verschlüsseln:
    43. Dim Data() As Byte
    44. Data = System.Text.Encoding.UTF8.GetBytes(DecryptedString)
    45. cs.Write(Data, 0, Data.Length)
    46. cs.FlushFinalBlock()
    47. cs.Close()
    48. ' Verschlüsselte Daten als String ausgeben:
    49. EncryptedString_ = Convert.ToBase64String(ms.ToArray)
    50. ms.Close()
    51. AES.Clear()
    52. End Sub
    53. ' Entschlüsseln
    54. Public Sub Decrypt(ByVal AESKeySize As Int32, _
    55. ByVal EncryptedString As String, _
    56. ByVal Password As String)
    57. ' Der Salt-Wert und das Passwort müssen mit dem übereinstimmen,
    58. ' das bei der Verschlüsselung verwendet wurde:
    59. Dim Salt() As Byte
    60. Salt = System.Text.Encoding.UTF8.GetBytes( _
    61. "123456789")
    62. Dim GenerierterKey As New Rfc2898DeriveBytes(Password, Salt)
    63. ' Instanzierung des AES-Algorithmus-Objekts:
    64. Dim AES As New AesManaged
    65. ' Ein mit 256 bit verschlüsselter String kann
    66. ' auch nur mit 256 bit entschlüsselt werden!
    67. AES.KeySize = AESKeySize ' möglich sind 256 oder 128 bit
    68. AES.BlockSize = 128
    69. ' Algorithmus initialisieren:
    70. AES.Key = GenerierterKey.GetBytes(AES.KeySize \ 8)
    71. AES.IV = GenerierterKey.GetBytes(AES.BlockSize \ 8)
    72. ' Memory-Stream und Crypto-Stream erzeugen -> CreateDecryptor()
    73. Dim ms As New IO.MemoryStream
    74. Dim cs As New CryptoStream(ms, AES.CreateDecryptor(), _
    75. CryptoStreamMode.Write)
    76. Try ' Daten entschlüsseln:
    77. Dim Data() As Byte
    78. Data = Convert.FromBase64String(EncryptedString)
    79. cs.Write(Data, 0, Data.Length)
    80. cs.FlushFinalBlock()
    81. cs.Close()
    82. ' Die entschlüsselten Daten als String ausgeben:
    83. DecryptedString_ = System.Text.Encoding.UTF8.GetString(ms.ToArray)
    84. ms.Close()
    85. AES.Clear()
    86. Catch ex As Exception
    87. DecryptedString_ = "Ungültiges Passwort!"
    88. End Try
    89. End Sub
    90. #End Region
    91. #Region "Eigenschaften"
    92. ReadOnly Property EncryptedString() As String
    93. Get
    94. Return EncryptedString_
    95. End Get
    96. End Property
    97. ReadOnly Property DecryptedString() As String
    98. Get
    99. Return DecryptedString_
    100. End Get
    101. End Property
    102. #End Region
    103. End Class



    Falls es was zu Optimieren gild nur her damit,
    also aktuell macht der halt feld für feld und ich dachte 5 gleichzeitig würde mehr bringen ;)
    Danke für die Hilfe!
    Hallo ,

    also bei meinem Youtube Bot mit der Youtube API habe ich es auch so gemacht das pro Aufgabe immer 3 Threads laufen die das gleiche machen...
    3 Threads waren schneller als einer.

    Also ich denke wenn man dann daraus nen paar Threads macht würde das auch schneller laufen.
    Wobei ich sagen muss.. Die Youtube Api Logt sich ein prüft den Key für den Dev... Diese Aufgabe dauert nacheinander einfach zu lange...

    Deshalb hab ich mir einfach 3 Threads für jede Aufgabe gemacht und es lief 3 mal schneller...

    In wie weit das nun auf dein Problem zutrifft kann ich dir nicht sagen ;)

    Sollte nur ein kleiner erfahrungsbericht sein hier ^^
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen

    Psike2k11 schrieb:

    ch habe mir das ganze mal beim durchlaufen der Datensätze angesehen die Auslastung liegt bei 10%

    Das zeigt entweder, dass du 3-6 Kerne hast, oder dass die IO Geschichte am meisten bremst.

    Je nach Dateigröße und verfügbarem Arbeitsspeicher ist es vermutlich sinnvoller, die GESAMTE Datei am Stück einzulesen (ReadLines()) und am Schluss auch am Stück zu schreiben.

    Statt Strings zu kombinieren, sollte man bei mehr Feldern den Stringbuilder verwenden. Strings sind "immutable" und bei jeder "Anfüge" Aktion wird einer komplett neuer String erzeugt und der alte verworfen.

    Außerdem kann man zum kombinieren .Join nehmen, anstatt selbst ne Schleife zu basteln.

    BTW: Damit Multithreading funktioniert, muss die encrypt Funktion natürlich threadsafe sein ... !

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

    Psike2k11 schrieb:

    ErfinderDesRades schrieb:

    nebenbei: Welche Funktion erfüllt das .ToString bei args(0).ToString ?
    Die funktion erwartet einen string wenn ich ihm die stellle im Array mitgebe sagt der debugger mir das er ein String erwartet und kein Array....

    Falsch. Das sagt der Debugger nur, wenn du ihm ein Array mitgibst (also args). Wenn du ihm aber ein Array-Element mitgibst (args(0)), dann sagter nix, denn args ist ein String-Array, also die Elemente von args sind bereits vom typ String, und macht kein guten Eindruck, wenn man String nach String umwandelt ;)

    Nanu??
    ist das jetzt ein Crosspost, oder ist der Thread abgetrennt worden?
    gugge [VB 2010] Mehr Infos

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

    Ja unten wohl auf "Neues Thema" gekommen als ich "Antworten" wollte, wieso gibts den Knopf obwohl ich mich in einem Thema befinde.....;)

    Mhh ok hast recht kein fehler....hab den sting jetzt im string Builder zusammen gesetzt vor dem schreiben bringt schon mal ordentlich was!

    ErfinderDesRades schrieb:

    richtig viel ist da mit threading nicht zu holen. naja, immerhin würde 2 Threads 2 kernels ausnutzen.
    mehr threads bringen nix, denn jeder Thread kriegt ja nur einen Anteil der insgesamt verfügbaren CPU-Power, und ob nun ein thread mit 100% arbeitet oder 5 Threads mit je 20% - kommt fast aufs selbe raus, ausser, dass bei 5 Threads noch einiges an Leistung für die Thread-Verwaltung draufgeht.
    Das ist nicht so.

    Testcode: Form, 2 Button, 3 Backgroundworker
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Feld1() As Double
    3. Private Feld2() As Double
    4. Private Summe1() As Double
    5. Private Summe2() As Double
    6. Private start As DateTime
    7. Private flag2 As Boolean
    8. Private flag3 As Boolean
    9. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    10. start = DateTime.Now
    11. flag2 = False
    12. flag3 = False
    13. BackgroundWorker1.RunWorkerAsync()
    14. End Sub
    15. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    16. start = DateTime.Now
    17. flag2 = False
    18. flag3 = False
    19. BackgroundWorker2.RunWorkerAsync()
    20. BackgroundWorker3.RunWorkerAsync()
    21. End Sub
    22. Private Sub InitArrays(ByRef feld() As Double, ByRef summe() As Double)
    23. Dim i As Integer
    24. Try
    25. For j = 0 To 9
    26. ReDim feld(1000000)
    27. ReDim summe(1000000)
    28. For i = 0 To feld.Length - 1
    29. feld(i) = CDbl(i) * CDbl(i)
    30. summe(i) = 0
    31. Next
    32. For i = 0 To feld.Length - 1
    33. summe(i) = Math.Sin(Math.Sqrt(feld(i)))
    34. Next
    35. Next
    36. Catch ex As Exception
    37. Stop
    38. End Try
    39. End Sub
    40. Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    41. InitArrays(Feld1, Summe1)
    42. InitArrays(Feld2, Summe2)
    43. End Sub
    44. Private Sub BackgroundWorker2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
    45. InitArrays(Feld1, Summe1)
    46. End Sub
    47. Private Sub BackgroundWorker3_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker3.DoWork
    48. InitArrays(Feld2, Summe2)
    49. End Sub
    50. Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    51. flag2 = True
    52. flag3 = True
    53. Finish()
    54. End Sub
    55. Private Sub BackgroundWorker2_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker2.RunWorkerCompleted
    56. flag2 = True
    57. Finish()
    58. End Sub
    59. Private Sub BackgroundWorker3_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker3.RunWorkerCompleted
    60. flag3 = True
    61. Finish()
    62. End Sub
    63. Private Sub Finish()
    64. If (Not (flag2 And flag3)) Then
    65. Return
    66. End If
    67. Dim ende As DateTime = DateTime.Now
    68. MessageBox.Show((ende - start).TotalSeconds.ToString)
    69. End Sub
    70. End Class
    Die auf 2 Backgroundworker verteilte Arbeit ist etwa in der halben Zeit beendet wie die von einem verrichtete.
    Das Betriebssystem verteilt Zeitscheiben an alle laufenden Prozesse.
    Wenn Dein Programm 1 Zeitscheibe von 100 Scheiben bekommt oder 2 Zeitscheiben von 101, ist das praktisch ein Faktor 2.
    Da ist es egal, wieviel Kerne der Prozessor hat.
    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!
    ich glaub aber doch. IMO ist dein Test deshalb schneller, weil du auf einer Maschine mit 2 o. mehr Kernel getestet hast. Da kanner natürlich beide Kernels hinzuziehen, und dadurch die Gesamtleistung des Compis besser ausnutzen, denn mit nur einem Thread kanner nur einen Kernel beauftragen.
    Ein korrekter Test müsste zunächst man in genau die Anzahl der Kernels aufteilen und messen.
    Und dann weiter aufteilen - AFAIK bringt das dann nix mehr.
    Soo nun hat sich folgendes ergeben ich hab das ergebnis jetzt mal komplett zurück gewandelt und hab festgestellt das der Ursprung Windows-1252 als encoding hat und in meinem Code benutze ich UTF-8 ... dummer weise weiss ich nicht wie ich test.encoding.XXX sagen kann das XXX 1252 ist hab nur UTF-7/8/32 und ASCII....was nun?
    Hab mal rumgespielt
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Threading
    2. Imports System.Threading.Tasks
    3. Imports System.Security.Cryptography
    4. Public Class Form1
    5. Private cryptcols() As Integer = {2, 3, 27, 31, 45}
    6. Private myfile As String = System.IO.Path.Combine(
    7. My.Computer.FileSystem.SpecialDirectories.CurrentUserApplicationData,
    8. "mydummy.txt")
    9. Private myfileout As String = myfile & ".out"
    10. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    11. End Sub
    12. Private Async Function ProcessFile(ByVal numthreads As Integer) As Tasks.Task(Of Tuple(Of Integer, Integer))
    13. Dim stp_compute As New Stopwatch
    14. Dim stp_all As New Stopwatch
    15. stp_all.Start()
    16. Dim line_in() As String = IO.File.ReadAllLines(myfile)
    17. ' segment the problem
    18. stp_compute.Start()
    19. Dim segsize As Integer = line_in.Count \ numthreads
    20. Dim masteraes As New AesManaged
    21. Dim pdb = New PasswordDeriveBytes("password", New Byte() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})
    22. masteraes.Key = pdb.GetBytes(masteraes.KeySize \ 8)
    23. masteraes.IV = pdb.GetBytes(masteraes.BlockSize \ 8)
    24. Dim dowork = New Action(Of Object)(Sub(param As Object)
    25. Dim tp As Tuple(Of Integer, Integer) = DirectCast(param, Tuple(Of Integer, Integer))
    26. Dim starti As Integer = tp.Item1
    27. Dim numi As Integer = tp.Item2
    28. Dim aes As New AesManaged
    29. aes.Key = masteraes.Key
    30. aes.IV = masteraes.IV
    31. For i = starti To starti + numi - 1
    32. Dim s() = line_in(i).Split(";")
    33. For Each n In cryptcols
    34. Using ms As New IO.MemoryStream
    35. Using cs As New CryptoStream(ms, aes.CreateEncryptor, CryptoStreamMode.Write)
    36. cs.Write(System.Text.Encoding.ASCII.GetBytes(s(n)), 0, s(n).Length)
    37. End Using
    38. s(n) = Convert.ToBase64String(ms.ToArray)
    39. End Using
    40. Next
    41. line_in(i) = Join(s, ";")
    42. Next
    43. End Sub)
    44. Dim tf As New Tasks.TaskFactory()
    45. Dim lt As New List(Of Tasks.Task)
    46. For t = 0 To numthreads - 1
    47. Dim sg As Integer
    48. If t = numthreads - 1 Then
    49. sg = line_in.Count - (numthreads - 1) * segsize
    50. Else
    51. sg = segsize
    52. End If
    53. lt.Add(tf.StartNew(dowork, New Tuple(Of Integer, Integer)(t * segsize, sg)))
    54. Next
    55. Await Tasks.TaskEx.WhenAll(lt)
    56. stp_compute.Stop()
    57. If My.Computer.FileSystem.FileExists(myfileout) Then My.Computer.FileSystem.DeleteFile(myfileout)
    58. IO.File.WriteAllLines(myfileout, line_in)
    59. stp_all.Stop()
    60. Return New Tuple(Of Integer, Integer)(stp_all.ElapsedMilliseconds, stp_compute.ElapsedMilliseconds)
    61. End Function
    62. Private Function CreateFile(ByVal zeilen As Integer, ByVal spalten As Integer) As Boolean
    63. If My.Computer.FileSystem.FileExists(myfile) Then
    64. If MessageBox.Show(Me, "Vorhandene Datei löschen?", "Datei gefunden", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then
    65. My.Computer.FileSystem.DeleteFile(myfile)
    66. Else
    67. Return True
    68. End If
    69. End If
    70. Dim inhalt As Integer = 1000000
    71. Dim b(spalten - 1) As String
    72. Dim str As System.IO.StreamWriter = New IO.StreamWriter(IO.File.OpenWrite(myfile))
    73. For i = 1 To zeilen
    74. For j = 0 To spalten - 1
    75. b(j) = inhalt.ToString("0000000")
    76. inhalt += 1
    77. Next
    78. str.WriteLine(Join(b, ";"))
    79. Next
    80. str.Close()
    81. Return True
    82. End Function
    83. Private Sub BtnCreateFile_Click(sender As System.Object, e As System.EventArgs) Handles BtnCreateFile.Click
    84. If CreateFile(1000000, 50) Then
    85. MessageBox.Show("Datei wurde erzeugt!" & vbCrLf & "Größe: " & New System.IO.FileInfo(myfile).Length \ (1000 * 1000) & " MB")
    86. End If
    87. End Sub
    88. Private Async Sub BtnDoWork_Click(sender As System.Object, e As System.EventArgs) Handles BtnDoWork.Click
    89. Dim n As Integer = nudThreads.Value
    90. Dim result As Tuple(Of Integer, Integer) = Await ProcessFile(n)
    91. Dim sout As String = String.Format("Threads: {0}, total: {1}, computeonly: {2}", n, result.Item1, result.Item2)
    92. Debug.Print(sout)
    93. lstResults.Items.Add(sout)
    94. End Sub
    95. End Class

    Vlt noch etwas unbeholfen, aber weiter optimieren kann man ja immer ;)

    EDIT: Erklärung:
    Es wird zuerstmal ne Datei mit 1.000.000 Zeilen und je 50 spalten erzeugt, die mit dummy-Werten gefüllt werden. Die Datei hat dann rund 400 MB.
    Bei der Verarbeitung wird die Datei komplett eingelesen (als Array) und dann arbeiten x Threads jeweils an Teilbereichen und verschlüsseln jeweils die spalten, die in "cryptcols" definiert wurden.
    Wenn alles fertig ist, wird die Datei komplett geschrieben. Wie man sieht, dauert allein schon das Lesen/Schreiben 5 Sekunden und da läßt sich auch kaum noch viel mehr Speed rausholen denke ich.

    Getestet auf Core i7-2600 (3.4G/4C/8T)

    Quellcode

    1. Threads: 1, total: 22048, computeonly: 17548
    2. Threads: 1, total: 22723, computeonly: 17157
    3. Threads: 1, total: 22624, computeonly: 17076
    4. Threads: 2, total: 15322, computeonly: 9914
    5. Threads: 2, total: 14713, computeonly: 9932
    6. Threads: 2, total: 15255, computeonly: 9868
    7. Threads: 4, total: 12139, computeonly: 6634
    8. Threads: 4, total: 12005, computeonly: 6372
    9. Threads: 4, total: 12016, computeonly: 6349
    10. Threads: 8, total: 11909, computeonly: 6403
    11. Threads: 8, total: 12233, computeonly: 6443
    12. Threads: 8, total: 11463, computeonly: 6308

    Wie man sieht bringt HT in diesem Fall nix und bei 4 Threads vs 1 kommt man auf etwa 35% Rechenzeit (optimal wären 25%)

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

    Nachtrag zu oben: der lief auf einem AMD-6
    XP mit Hyperthreading ergab keinen Unterschied.
    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!

    Psike2k11 schrieb:

    dummer weise weiss ich nicht wie ich test.encoding.XXX sagen kann

    System.Text.Encoding.GetEncoding(1252).GetBytes(meinstring)
    schon probiert?

    BTW: Muss eigentlich jeder EINZELNE Datensatz dekodierbar sein, oder reicht es, wenn das gesamte Dok bei seiner Rückkehr wieder dekodiert werden kann? Bei zweiterem würde mir nämlich ein guter Trick einfallen ;)

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

    Ist jetzt schon eine weile her aber ich war im Urlaub,
    die Datei muss eine CSV bleiben und jeder Datensatz muss verschlüsselt sein...wird auf der Gegenseite auch Datensatz für Datensatz eingelesen!
    In der Zwischenzeit habe ich alles auf No Hands On programmiert da sich das ganze säter in ein WorkFlow einbauen lassen soll!

    Also überwache ich einen Ordner in den kommen die Datei und werden am ende wenn das Umwandel abgeschlossen ist auf einen FTP Server verschoben

    So jetzt habe ich 2 Sachen generell macht das nicht das jede Datei ca. 1 Stunde braucht wenn sich keiner drum kümmern muss egal.
    Aber wenn ich das starte hängt leider die Main GUI und tut nix mehr das Programm encrypted fleißig weiter und am ende hat man auch ne 100% datei aber ich will nicht das was hängt ;)
    Und ich überlege ob auf einem Server mit 16 Kernen nicht doch was aus Threads rauszuholen ist!
    Der String builder hat nur MINIMAL was gebracht!

    Danke für die Hilfe
    Du musst halt nur beachten, dass ich mit einer "kleinen" Datei von rund 400 MB arbeite. Wenn deine Datei DEUTLICH größer ist musst du ggf außen rum noch ne Schleife bauen, so dass die die gesamte Datei nicht am Stück liest und schreibst, sondern immer "häppchenweise" - wobei ein Happen irgendwas zwischen 100 MB und 1 GB sein kann!