Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 15 sur 15
  1. #1
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut [VB.NET] BackgroundWorker trés lent

    Je viens de mettre en place un BackgroundWorkerpour gérer une partie de mon code (en vb.net) qui est très longue.
    La fonction que j'utilisais avant a été transposée dans une fonction déclenchée par l'event BackgroundWorker.DoWork
    J'ai aussi mis en place un BackgroundWorker.ProgressChanged pour suivre la progression de la tache, ainsi que BackgroundWorker.RunWorkerCompleted pour gérer la fin.

    Or j'ai remarqué que la même tache exécutée dans mon BackgroundWorker est sensiblement plus longue (X10) par rapport à la même tache dans mon thread principal.

    J'ai essayé de commenter la ligne BackgroundWorker.ReportProgress() , mais cela n'y a rien changé.

    Est-ce que j'ai loupé quelque chose?
    Est-ce que les BackgroundWorker sont par nature plus lents?

  2. #2
    Expert Confirmé
    Avatar de GuruuMeditation
    Homme Profil pro Olivier Matis
    .Net Architect
    Inscrit en
    octobre 2010
    Messages
    1 618
    Détails du profil
    Informations personnelles :
    Nom : Homme Olivier Matis
    Âge : 39
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : octobre 2010
    Messages : 1 618
    Points : 3 397
    Points
    3 397

    Par défaut

    Il ne devrait pas y avoir de différences. Tu fais quoi dans le BackgroundWorker?
    Microsoft MVP : Windows Platform

    MCPD - Windows Phone Developer
    MCPD - Windows Developer 4

    http://www.guruumeditation.net

    “If debugging is the process of removing bugs, then programming must be the process of putting them in.”
    (Edsger W. Dijkstra)

  3. #3
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Citation Envoyé par GuruuMeditation Voir le message
    Il ne devrait pas y avoir de différences. Tu fais quoi dans le BackgroundWorker?
    La même chose que je faisais dans le thread principal avant :
    Je liste de façon récursive les fichiers contenus dans un répertoire ainsi que ses sous-répertoires, et je reporte ça dans une bdd mysql.
    Est-ce que le fait que 2 threads (principal + BackgroundWorker) accèdent à la même bdd en même temps peut ralentir chacun d'eux?

  4. #4
    Expert Confirmé
    Avatar de GuruuMeditation
    Homme Profil pro Olivier Matis
    .Net Architect
    Inscrit en
    octobre 2010
    Messages
    1 618
    Détails du profil
    Informations personnelles :
    Nom : Homme Olivier Matis
    Âge : 39
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : octobre 2010
    Messages : 1 618
    Points : 3 397
    Points
    3 397

    Par défaut

    Est-ce que tu as essaye de mesurer, dans le backgroundworker quelle partie prend plus de temps? Avec un profileur, par exemple.
    Microsoft MVP : Windows Platform

    MCPD - Windows Phone Developer
    MCPD - Windows Developer 4

    http://www.guruumeditation.net

    “If debugging is the process of removing bugs, then programming must be the process of putting them in.”
    (Edsger W. Dijkstra)

  5. #5
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Je viens de faire plusieurs tests avec le BackgroundWorker, et même un thread à part pour évaluer le temps nécessaire à l’exécution de mon script.
    En fait le report en bdd des résultats au fil de l'eau prends pas mal de temps.
    Mais ce qui en prend encore plus c'est le fait de tester la disponibilité du fichier (est-ce qu'il est déjà ouvert dans un autre programme ou pas) ainsi que la récupération d'infos comme sa date de création....
    Je vais continuer mes tests pour avoir un temps d’exécution via le BackgroundWorker par apport à la même exécution dans le thread principal...

  6. #6
    Modérateur
    Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : février 2006
    Messages : 754
    Points : 1 174
    Points
    1 174

    Par défaut

    Bonsoir,

    Un bout de code vaut mieux qu' un long discours. Envoie les 2 codes et on pourra éventuellement trouver ce qui ne va pas. Sinon tu as utilisé directory.getfiles ou enumeratefiles?
    Un âne se croit savant parce qu'on le charge de livres (proverbe américain)

    N'oubliez pas de avant de
    Pas de question techniques par MP, c'est contre la philosophie du forum

  7. #7
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Au vu des résultats que j'obtiens, je pense que je vais surement changer la construction de mon code, mais je vous laisse juger :

    J'ai fais 3 tests :
    1) avec un backgroundworker qui exécute la même fonction + une progress barre et un label qui indique le %tage d'avancement
    2) avec un vrai autre thread qui exécute la même fonction + une progress barre et un label qui indique le %tage d'avancement
    3) dans le thread principal, comme actuellement (par exemple quand on appuie sur un bouton)

    Attention dans le cas d'un thread en plus, le thread principal continue à exécuter des fonction/requêtes mysql en même temps

    J'ai pris un rep contenant 4112 fichiers répartis dans plus de 100 rep pour un total de plusieurs Go afin de tester la rapidité des différentes solutions.

    thread principal
    simple 2'36''
    sans report bdd 17''
    sans report bdd, ni test dispo 5''

    BackgroundWorker
    simple 5'
    sans report progress 5'09''
    sans report bdd 3'08''

    Thread secondaire
    simple 4'49''
    sans report bdd 1'35''
    sans report bdd, ni test dispo 5''

    Mon code ressemble à ça (cas du thread secondaire, pour le reste il suffit de lancer la fonction directement à partir du BGW ou du thread principal, en changeantce qui est propre à chacun) :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
        Private Sub LaunchListMediaThread()
            NewMediaToList = False
            Dim Medias As String = ""
            Dim count As Integer = 0
     
            RemplListMediasThread(FilePath, Medias, count)
            If Medias.Length > 0 Then Medias = Medias.Remove(0, 1)
            MediaTab_Temp = Medias.Split("|")
        End Sub
     
     
        Sub RemplListMediasThread(ByVal RepPere As String, ByRef MediaConcatString As String, ByRef count_avancement As Integer)
            Application.DoEvents()
     
            Dim ListOfRep() As String = Directory.GetDirectories(RepPere)
     
            For indexrep = 0 To ListOfRep.Length - 1
                RemplListMediasThread(ListOfRep(indexrep), MediaConcatString, count_avancement)
            Next
     
            Dim ListOfFiles() As String = System.IO.Directory.GetFileSystemEntries(RepPere, "*.*")
     
            For indexfile = 0 To ListOfFiles.Length - 1
                count_avancement += 1
     
                SetLabelText_ThreadSafe(Me.LabelMedia, count_avancement)
                SetPBValue_ThreadSafe(Me.MediaProgressBar, count_avancement)
     
                Try
                    Dim DateCreation As Date = FileDateTime(ListOfFiles(indexfile))
                    Dim DiffDate As Integer = DateDiff(DateInterval.Minute, DateCreation, Now)
     
                    If FileOk(ListOfFiles(indexfile),DiffDate) Then
                        MediaConcatString = MediaConcatString & "|" & ListOfFiles(indexfile)
                       AddToMediaTableBackThread(Path.GetFileName(ListOfFiles(indexfile)), "1", DateCreation.ToString("yyyy-MM-dd H:mm:ss"))
                       End If
                Catch ex As Exception
     
                End Try
     
                Application.DoEvents()
            Next
        End Sub
     
     
        Sub AddToMediaTableBackThread(ByVal MediaFileName As String, ByVal Statut As String, ByVal DateModif As String)
            Dim MySqlString As String = "INSERT INTO " & MysqlPrefixTable & "medias (`media` ,`statut`, `filedate`) VALUES " & " ('" & MediaFileName & _
                                       "', '" & Statut & "', '" & DateModif & "')" & " ON DUPLICATE KEY UPDATE statut='" & Statut & "', filedate='" & DateModif & "';"
            Dim MyCommand As New MySqlCommand
            Dim MediaMysqlConn As New MySqlConnection
            MediaMysqlConn.ConnectionString = MyConnectionString
            MyCommand.Connection = MediaMysqlConn
            MyCommand.CommandText = MySqlString
     
            Try
                MediaMysqlConn.Open()
                MyCommand.ExecuteNonQuery()
                MediaMysqlConn.Close()
            Catch myerror As MySqlException
     
            End Try
     
            MyCommand.Dispose()
        End Sub
     
     
     
        Delegate Sub SetPBValue_Delegate(ByVal [PB] As ProgressBar, ByVal [value] As Integer)
     
        Private Sub SetPBValue_ThreadSafe(ByVal [PB] As ProgressBar, ByVal [value] As Integer)
            Dim pourcent As Integer = 0
            pourcent = CInt([value] * 100 / (TotalPrecendent + 2))
            If pourcent > 100 Then
                pourcent = 100
            ElseIf pourcent < 0 Then
                pourcent = 0
            End If
     
            If [PB].InvokeRequired Then
                Dim MyDelegate As New SetPBValue_Delegate(AddressOf SetPBValue_ThreadSafe)
                Me.Invoke(MyDelegate, New Object() {[PB], [value]})
            Else
                [PB].Value = pourcent
            End If
        End Sub
    J'ai simplifié plusieurs choses, comme FileOk qui teste si le fichier n'est pas utilisé ailleurs (en faisant une tentative de renommage) ou si sa copie est bien terminée...
    Pour les tests, j'ai retiré la gestion des exceptions pour simplifier.

    La conclusion est quand même que pour l’exécution du MÊME code dans un thread en plus, avec les mêmes paramètres, cela prends:
    - 5 minutes avec le Backgroundworker
    - 4'49'' avec le thread de Threading.Thread
    alors que dans le thread principal cela prend 2'36.

    D’où ma question sur la rapidité des thread secondaires ET/OU si le fait de faire en même temps des requêtes dans un thread en parallèle peut ralentir un autre thread...

  8. #8
    Expert Confirmé Sénior Avatar de Graffito
    Inscrit en
    janvier 2006
    Messages
    5 809
    Détails du profil
    Informations forums :
    Inscription : janvier 2006
    Messages : 5 809
    Points : 7 505
    Points
    7 505

    Par défaut

    Il me semble probable que la perte de performance vienne de l'utilisation de Application.DoEvents() normalement inutile si on utilise un BackGroundWorker (pour le multithread, plutôt utiliser un Invoke pour mettre à jour la form)
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  9. #9
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Citation Envoyé par Graffito Voir le message
    Il me semble probable que la perte de performance vienne de l'utilisation de Application.DoEvents() normalement inutile si on utilise un BackGroundWorker (pour le multithread, plutôt utiliser un Invoke pour mettre à jour la form)
    C'était une bonne piste, mais j'ai fait les tests avec et sans Application.DoEvents() et la fonction prends autant de temps...

  10. #10
    Expert Confirmé Sénior Avatar de Graffito
    Inscrit en
    janvier 2006
    Messages
    5 809
    Détails du profil
    Informations forums :
    Inscription : janvier 2006
    Messages : 5 809
    Points : 7 505
    Points
    7 505

    Par défaut

    Lorsque que tu ouvre le gestionnaire de tâche pour observer l'utilisation des processeurs, quel sont les taux d'utilisation des differents processeurs ?
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  11. #11
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Citation Envoyé par Graffito Voir le message
    Lorsque que tu ouvre le gestionnaire de tâche pour observer l'utilisation des processeurs, quel sont les taux d'utilisation des differents processeurs ?
    7-12% pendant l'éxécution du thread secondaire
    1-7% sinon

  12. #12
    Modérateur
    Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : février 2006
    Messages : 754
    Points : 1 174
    Points
    1 174

    Par défaut

    Bonjour,

    Citation Envoyé par Morphee_ Voir le message
    Je liste de façon récursive les fichiers contenus dans un répertoire ainsi que ses sous-répertoires, et je reporte ça dans une bdd mysql.
    Est-ce que le fait que 2 threads (principal + BackgroundWorker) accèdent à la même bdd en même temps peut ralentir chacun d'eux?
    Maintenant qu'on a écarté les problèmes de performance de code, en relisant les réponses depuis le début, il y a un point sur lequel tu as insisté et auquel nous n'avons pas répondu, oui si tes deux threads font des modifications en base de données sur la même table, les deux threads peuvent être pénalisés.

    Désolé de ne pas avoir tilté plus tôt...
    Un âne se croit savant parce qu'on le charge de livres (proverbe américain)

    N'oubliez pas de avant de
    Pas de question techniques par MP, c'est contre la philosophie du forum

  13. #13
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Citation Envoyé par sisqo60 Voir le message
    Bonjour,

    Maintenant qu'on a écarté les problèmes de performance de code, en relisant les réponses depuis le début, il y a un point sur lequel tu as insisté et auquel nous n'avons pas répondu, oui si tes deux threads font des modifications en base de données sur la même table, les deux threads peuvent être pénalisés.

    Désolé de ne pas avoir tilté plus tôt...
    Alors, ça me parait assez logique, mais sans aucune requête en bdd, j'ai aussi une différence de temps d’exécution....

  14. #14
    Modérateur
    Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : février 2006
    Messages : 754
    Points : 1 174
    Points
    1 174

    Par défaut

    Une différence de quel ordre? Tu seras pénalisé aussi si tu lis des fichiers sur le disque, sauf si tu as un disque dur SSD, tout dépend de la quantité et de la taille des fichiers que tu lis. Ça dépend aussi du fait que ton disque dur soit ou non defragmenté, du cache de ton disque dur... bref ça devient compliqué du fait des paramètres à prendre en compte...
    Un âne se croit savant parce qu'on le charge de livres (proverbe américain)

    N'oubliez pas de avant de
    Pas de question techniques par MP, c'est contre la philosophie du forum

  15. #15
    Candidat au titre de Membre du Club
    Inscrit en
    février 2011
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : février 2011
    Messages : 27
    Points : 10
    Points
    10

    Par défaut

    Citation Envoyé par sisqo60 Voir le message
    Une différence de quel ordre? Tu seras pénalisé aussi si tu lis des fichiers sur le disque, sauf si tu as un disque dur SSD, tout dépend de la quantité et de la taille des fichiers que tu lis. Ça dépend aussi du fait que ton disque dur soit ou non defragmenté, du cache de ton disque dur... bref ça devient compliqué du fait des paramètres à prendre en compte...
    Bah cf plus haut, sans éxécuter la fonction AddToMediaTableBackThread :
    - thread principal : 17''
    - thread secondaire 1'37''
    - backgroundworker 3'08''.
    Certes, je n'ai fait qu'une mesure et pas plusieurs pour moyenner, mais il y a quand même une grosse différence dans l'ordre de grandeur !
    Pour mes tests, se sont plutôt des "petits" fichiers, mais pour mon application pratique ça sera des fichiers assez gros (20-300Mo).
    Je suis d'accord que tous ces paramètres entrent en compte, mais s'ils sont les mêmes à chaque fois, pourquoi un thread secondaire et le thread principal n'ont pas les mêmes perf, ça me parait anormal....

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •