Reine Performance und Stilfrage

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von DannyDee.

    Reine Performance und Stilfrage

    Hallö'chen Leute,
    ich habe in der Firma eine Übungsaufgabe gestellt bekommen. Und zwar habe ich einen Inkremental Drehgeber mit 2 Näherrungssensoren gebaut und lese diese nun über ein Programm ,welches in ich VB (2010) verfasst habe aus. Das klappt alles soweit ganz gut. DIe Näherungssensoren schaffen eine Frequenz bis 1khz. Aber sofern die Informationen die ich habe richtig sind ,kann ein USB durchschnittlich alle 25ms eine Info übertragen. Damit wäre ich soweit ja auch zufrieden ,doch das Programm arbeitet mir zu langsam.
    Da ich noch ein relativer Neuling bin ,wollte ich mal eure Meinung dazu wissen ,was ich am Quellcode verbessern kann. Das Hauptaugenmerk meinerseits liegt auf "If-Else". Wäre super ,wenn ihr zu einer gewissen Stelle an der ihr etwas ersetzen würdet einfach ein Stichwort mit rein bringt. Den Rest lese ich mir dann zusammen :)

    Naja hier der Code:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Imports FirmaXP.BusPort
    4. Imports FirmaXP.BusFunctions
    5. Public Class Main
    6. Dim A As Integer 'Sensor A
    7. Dim B As Integer 'Sensor B
    8. Dim max As Integer = 120 'Maximum Lautstärke
    9. Dim mini As Integer = 0 'Minimum Lautstärke
    10. Private DT As DataTable 'Datentabelle zum Anzeigen der Feldmodule(Firmenintern)
    11. Private Sub init()
    12. DT = New DataTable
    13. With DT
    14. .Columns.Add("Name")
    15. .Columns.Add("KurzAdr")
    16. .Columns.Add("TypNR")
    17. .Columns.Add("LangAdr")
    18. End With
    19. With Me.DataGridView1
    20. .DataSource = DT
    21. .AllowUserToAddRows = False
    22. .ReadOnly = True
    23. .RowHeadersVisible = False
    24. End With
    25. End Sub
    26. Private Sub fillDT()
    27. DT.Rows.Clear()
    28. Dim devices As List(Of FirmaXP.Device) = FirmaXP.BusFunctions.devScan()
    29. If devices Is Nothing Then Exit Sub
    30. Dim dr As DataRow
    31. For Each d As FirmaXP.Device In devices
    32. dr = DT.NewRow
    33. dr("Name") = d.DevName
    34. dr("TypNR") = d.TypeNr
    35. dr("LangAdr") = d.LongAdr
    36. dr("KurzAdr") = d.ShortAdr
    37. DT.Rows.Add(dr)
    38. Next
    39. End
    40. End Sub 'Für das Programm irrelevant.
    41. Private Sub bt_search_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_search.Click
    42. init()
    43. fillDT()
    44. End Sub
    45. 'Aktivierung/Deaktivierung des Timers zum Auslesen des Registers (Gegenseitige Verriegelung)
    46. Private Sub cmd_lesen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_lesen.Click
    47. If timer_lesen.Enabled = False Then
    48. cmd_lesen.Text = "Bestimmung beenden."
    49. num_shadr.ReadOnly = True
    50. num_reg.ReadOnly = True
    51. timer_lesen.Enabled = True
    52. ElseIf timer_lesen.Enabled = True Then
    53. cmd_lesen.Text = "Drehrichtung bestimmen."
    54. num_shadr.ReadOnly = False
    55. num_reg.ReadOnly = False
    56. timer_lesen.Enabled = False
    57. End If
    58. End Sub
    59. 'Timer zum auslesen und Umsetzen des Codes in eine Anzeige der einzelnen Flanken
    60. Private Sub timer_lesen_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer_lesen.Tick
    61. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1536 Then
    62. tb_flankea.Text = "0"
    63. tb_flankeb.Text = "0"
    64. End If
    65. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1537 Then
    66. tb_flankea.Text = "1"
    67. tb_flankeb.Text = "0"
    68. End If
    69. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1538 Then
    70. tb_flankea.Text = "0"
    71. tb_flankeb.Text = "1"
    72. End If
    73. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1539 Then
    74. tb_flankea.Text = "1"
    75. tb_flankeb.Text = "1"
    76. End If
    77. End Sub
    78. 'Richtungserkennung Flanke A / Lautstärkenanzeige-Update
    79. Private Sub tb_flankea_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankea.TextChanged
    80. If tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "0" AndAlso TextBox1.TextLength < max Then
    81. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    82. TextBox1.Text = TextBox1.Text + "||| "
    83. ElseIf tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "1" AndAlso TextBox1.TextLength > mini Then
    84. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    85. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    86. End If
    87. End Sub
    88. 'Richtungserkennen Flanke B / Lautstärkenanzeige-Update
    89. Private Sub tb_flankeb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankeb.TextChanged
    90. If tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "0" AndAlso TextBox1.TextLength > mini Then
    91. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    92. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    93. ElseIf tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "1" AndAlso TextBox1.TextLength < max Then
    94. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    95. TextBox1.Text = TextBox1.Text + "||| "
    96. End If
    97. End Sub
    98. End Class


    Ich hoffe ihr könnt damit etwas anfangen und mir ein paar Tipps zur Performanceverbesserung geben.
    MfG

    Danny Der Dee

    DannyDee schrieb:

    VB.NET-Quellcode

    1. Private Sub timer_lesen_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer_lesen.Tick
    2. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1536 Then
    3. tb_flankea.Text = "0"
    4. tb_flankeb.Text = "0"
    5. End If
    6. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1537 Then
    7. tb_flankea.Text = "1"
    8. tb_flankeb.Text = "0"
    9. End If
    10. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1538 Then
    11. tb_flankea.Text = "0"
    12. tb_flankeb.Text = "1"
    13. End If
    14. If readReg(CInt(num_shadr.Value), CInt(num_reg.Value)) = 1539 Then
    15. tb_flankea.Text = "1"
    16. tb_flankeb.Text = "1"
    17. End If
    18. End Sub


    Wieso rufst du readReg mehrmals hintereinander? Speichere den Rückgabewert am Anfang in einer Variable und mach dann Select Case nach dieser Variable.

    sonne75 schrieb:

    Wieso rufst du readReg mehrmals hintereinander? Speichere den Rückgabewert am Anfang in einer Variable und mach dann Select Case nach dieser Variable.

    Ha! Da hast du wohl recht. :D Danke fürs Augen aufreißen. Montagmorgens bin ich immer so verpeilt. :)
    Ich werd`s auf jeden Fall umsetzen.

    Edit :
    Btw. Hat jemand eine konkretes Beispiel dafür ,wie ich folgendes durch Select Case ersetzen kann, da ich ja mit der If-Klausel 3 Bedinungen festgelegt habe.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Richtungserkennung Flanke A / Lautstärkenanzeige-Update
    2. Private Sub tb_flankea_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankea.TextChanged
    3. If tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "0" AndAlso TextBox1.TextLength < max Then
    4. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    5. TextBox1.Text = TextBox1.Text + "||| "
    6. ElseIf tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "1" AndAlso TextBox1.TextLength > mini Then
    7. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    8. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    9. End If
    10. End Sub
    11. 'Richtungserkennen Flanke B / Lautstärkenanzeige-Update
    12. Private Sub tb_flankeb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankeb.TextChanged
    13. If tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "0" AndAlso TextBox1.TextLength > mini Then
    14. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    15. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    16. ElseIf tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "1" AndAlso TextBox1.TextLength < max Then
    17. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    18. TextBox1.Text = TextBox1.Text + "||| "
    19. End If
    20. End Sub

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

    @DannyDee:
    Ich glaube, da liegt ein Designfehler vor.
    Was sind die TextBoxen(?) tb_flankea und tb_flankeb?
    Es ist wesentlich unperformanter, den Text eines Controls abzurufen und zwei Strings zu vergleichen, als einen Boolean zu prüfen. Denn so wie ich das sehe, kann das, was im Moment in den TextBoxen gespeichert wird, auch problemlos in einer Boolean-Variable gespeichert werden.
    Merk Dir diesen Grundsatz: Controls sind zum Anzeigen und Entgegennehmen von Daten da, aber nicht zum zwischenspeichern.

    Übrigens: Ab Zeile 51 im Code im Startpost:
    Das liese sich ersetzen durch folgendes:

    VB.NET-Quellcode

    1. Dim Flag = Not TimerXY.Enabled 'Wenn er vorher aktiviert war, enthält Flag jetzt, dass er deaktiviert sein soll.
    2. TimerXY.Enabled = Flag
    3. If Flag Then
    4. 'Wenn aktiviert
    5. Else
    6. 'Wenn deaktiviert
    7. End If


    Noch übrigenser: Das Vergleichen einer Boolean-Variable mit True bzw. False ist unnötig und kostet sogar (auch wenn das im Endeffekt nicht merkbar ist) Performance.
    Weiters gilt: Wenn die Variable nicht True ist, dann kann sie nur noch False sein. Also ein weiteres Prüfen auf das entsprechende Gegenstück ist unnötig.
    Also nicht

    VB.NET-Quellcode

    1. If Variable = True Then
    2. 'True-Teil
    3. ElseIf Variable = False Then
    4. 'False-Teil
    5. End If

    sondern

    VB.NET-Quellcode

    1. If Variable Then
    2. 'True-Teil
    3. Else
    4. 'False-Teil
    5. End If
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Niko Ortner schrieb:

    Was sind die TextBoxen(?) tb_flankea und tb_flankeb?
    Diese Textboxen sind dadurch entstanden ,dass ich die einzelnen Stellpositionen der Sensoren anzeigen wollte. Das tun sie ja auch, und da dachte ich mir: "Hey , wenn ich dort schon die Binärwerte stehen hab nehm ich sie doch einfach von dort." Aber deine Erklärung klingt einleuchtend :D Ich werde es mit Freuden umsetzen.



    Niko Ortner schrieb:

    Noch übrigenser: Das Vergleichen einer Boolean-Variable mit True bzw. False ist unnötig und kostet sogar (auch wenn das im Endeffekt nicht merkbar ist) Performance.
    Weiters gilt: Wenn die Variable nicht True ist, dann kann sie nur noch False sein. Also ein weiteres Prüfen auf das entsprechende Gegenstück ist unnötig.
    Also nicht
    Spoiler anzeigen

    VB.NET-Quellcode

    1. If Variable = True Then
    2. 'True-Teil
    3. ElseIf Variable = False Then
    4. 'False-Teil
    5. End If


    Ich schätze das war auf den Timer bezogen, oder? :) Habe es eben geändert.

    das einzige was ich nun noch umsetzen muss ist die Sache mit dem Flag.
    Edit folgt sofern ich es erfolgreich umgesetzt habe.

    Wird die Flag in deinem Beispiel als Booleanischer Wert deklariert oder als was? Da ich mit Option Strict On arbeite möchte er ein genaue Deklaration.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim Flag = Not TimerXY.Enabled 'Wenn er vorher aktiviert war, enthält Flag jetzt, dass er deaktiviert sein soll.
    2. TimerXY.Enabled = Flag
    3. If Flag Then
    4. 'Wenn aktiviert
    5. Else
    6. 'Wenn deaktiviert
    7. End If

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

    @DannyDee:
    Was ich gemacht habe, ist vollkommen Option Strict On -konform.
    Nimm als Beispiel diese Zeile:

    VB.NET-Quellcode

    1. Dim Test = "Hallo Welt"

    Welchen Typ hat nun die Variable Test?
    Die Antwort ist: String.
    Der Compiler weiß, dass der zugewiesene Wert vom Typ String ist. Deshalb kann man die Typangabe hier weglassen.
    Das ist extrem praktisch. Vergleiche diese beiden Codes:

    VB.NET-Quellcode

    1. Sub EmitToMethod(Method As System.Reflection.Emit.MethodBuilder)
    2. Dim MethodIL As System.Reflection.Emit.ILBuilder = Method.GetILGenerator()
    3. Dim LoopStartLabel As System.Reflection.Emit.Label = MethodIL.DefineLabel()
    4. '...

    VB.NET-Quellcode

    1. Sub EmitToMethod(Method As System.Reflection.Emit.MethodBuilder)
    2. Dim MethodIL = Method.GetILGenerator()
    3. Dim LoopStartLabel = MethodIL.DefineLabel()
    4. '...

    Bei C# gibt's das var-Schlüsselwort:

    C-Quellcode

    1. System.Reflection.Emit.ILGenerator MethodIL = Method.GetILGenerator();

    C-Quellcode

    1. var MethodIL = Method.GetILGenerator();


    Dadurch spart man sich einfach die Schreibarbeit. Beim Arbeiten mit anonymen Typen geht das garnicht anders. Denn man kann den Typ nicht hinschreiben (weil er anonym ist).

    Das Ganze ist ein Schalter wie Option Strict und nennt sich Option Infer.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Habe gegoogelt, "Infer On" ist erst ab 2008 möglich. Musst als auf Boolean stellen.

    Wo erscheint denn der Fehler beim Laden des Formulars? Was genau steht da drin und an welcher Stelle?

    EDIT: habe es selbst gefunden. Du hast deine Flag Variable gleich am Anfang des Programms deklariert, das ist auch ok. Nur weist du ihr an dieser Stelle auch schon den Wert zu, zu diesem Zeitpunkt gibt es aber weder den Timer noch seine Eigenschaft "Enabled", denn diese werden erst bei "InitializeComponents()" deklariert.

    Du musst dem Flag den Wert erst zuweisen, wenn du ihn brauchst.

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

    sonne75 schrieb:

    EDIT: habe es selbst gefunden. Du hast deine Flag Variable gleich am Anfang des Programms deklariert, das ist auch ok. Nur weist du ihr an dieser Stelle auch schon den Wert zu, zu diesem Zeitpunkt gibt es aber weder den Timer noch seine Eigenschaft "Enabled", denn diese werden erst bei "InitializeComponents()" deklariert.


    Haha. Hätte ich auch selbst drauf kommen können :)
    Vielen Dank @Sonne75

    Was ich mich nun noch frage ,ist ob ich die Drehrichtungserkennung eventuell einfacher gestalten kann , (ohne über die Controls zu gehen). Da hat mich FreakJNS drauf aufmerksam gemacht.
    Hier mal der zusammengehörende Code ,an dem man den Ausgabewert der Stellungen in Positionen der Sensoren umgewandelt sieht.

    Siehe QC:
    Spoiler anzeigen

    Auslesen und Umwandeln des Registerwertes

    VB.NET-Quellcode

    1. 'Timer zum auslesen und Umsetzen des Codes in eine Anzeige der einzelnen Flanken
    2. Private Sub timer_lesen_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timer_lesen.Tick
    3. Select Case readReg(CInt(num_shadr.Value), CInt(num_reg.Value))
    4. Case 1536
    5. tb_flankea.Text = "0"
    6. tb_flankeb.Text = "0"
    7. Case 1537
    8. tb_flankea.Text = "1"
    9. tb_flankeb.Text = "0"
    10. Case 1538
    11. tb_flankea.Text = "0"
    12. tb_flankeb.Text = "1"
    13. Case 1539
    14. tb_flankea.Text = "1"
    15. tb_flankeb.Text = "1"
    16. End Select
    17. End Sub



    Drehrichtungserkennung durch Texterfassung der Textboxen

    VB.NET-Quellcode

    1. 'Richtungserkennung Flanke A / Lautstärkenanzeige-Update
    2. Private Sub tb_flankea_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankea.TextChanged
    3. If tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "0" AndAlso TextBox1.TextLength < max Then
    4. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    5. TextBox1.Text = TextBox1.Text + "||| "
    6. ElseIf tb_flankea.Text = "1" AndAlso tb_flankeb.Text = "1" AndAlso TextBox1.TextLength > mini Then
    7. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    8. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    9. End If
    10. End Sub
    11. 'Richtungserkennung Flanke B / Lautstärkenanzeige-Update
    12. Private Sub tb_flankeb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb_flankeb.TextChanged
    13. If tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "0" AndAlso TextBox1.TextLength > mini Then
    14. tb_drehrichtung.Text = "Drehrichtung : Gegen den Uhrzeigersinn!"
    15. TextBox1.Text = TextBox1.Text.Remove(TextBox1.Text.Length - 4, 4)
    16. ElseIf tb_flankeb.Text = "1" AndAlso tb_flankea.Text = "1" AndAlso TextBox1.TextLength < max Then
    17. tb_drehrichtung.Text = "Drehrichtung : Mit dem Uhrzeigersinn!"
    18. TextBox1.Text = TextBox1.Text + "||| "
    19. End If
    20. End Sub


    Mir fällt dazu leider nichts vernünftiges ein.


    EDIT: Habe nun eine schönes Lösung gefunden. Der Thread kann wird als abgeschlossen markiert.
    Danke für eure Hilfe ;)

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