dimitriusai
Messages postés76Date d'inscriptionlundi 6 novembre 2006StatutMembreDernière intervention 7 mai 2009
-
8 mars 2008 à 08:21
laurent207
Messages postés101Date d'inscriptionjeudi 31 janvier 2002StatutMembreDernière intervention11 avril 2008
-
11 avril 2008 à 13:35
Amis programmeurs du week end, bonjour.
J'ai dévelloppé une petite application qui a mes yeux semblent avoir un soucis, en effet, celle ci prend de la mémoire de facon démessurée, elle démarre à 10000ko et ne fait qu'augmenter.
Le problème ne semble pas venir de la connection sql car en la commentant, cela fait le même problème. Je crois que c'est à cause des WMI, si qqun a une idée
Imports System
Imports System.EventArgs
Imports System.Management
Imports System.Threading
Public Class Service1
'Ip du serveur MySql.
Dim SQL_server As String = "**********"
'User id MySql.
Dim SQL_userid As String = "*******"
'User password Mysql.
Dim SQL_password As String = "**************"
'Database MySql.
Dim SQL_DATABASE As String = "************"
Dim my_memory As Double
Dim my_memory_total(4) As Double
Dim my_server As String
Dim my_cpu As Double
Dim my_cpu_total(4) As Double
Dim my_cpu_load As Double
Dim my_cpu_frequency_max As Integer
Dim my_cpu_frequency_use As Integer
Dim boucle As String = ""
Dim VDLB_VAR As New VDLB()
Protected Overrides Sub OnStart(ByVal args() As String)
Perf()
' Ajoutez ici le code pour démarrer votre service. Cette méthode doit
' démarrer votre service.
End Sub
Protected Overrides Sub OnStop()
' Ajoutez ici le code pour effectuer les destructions nécessaires à l'arrêt de votre service.
End Sub
Sub Perf()
Do
Dim i As Integer
For i = 0 To 4
Try
Dim searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_OperatingSystem")
For Each queryObj As ManagementObject In searcher.Get()
Dim max_memory As Double = (queryObj("TotalVisibleMemorySize"))
Dim available_memory As Double = (queryObj("FreePhysicalMemory"))
my_memory = (1 - (available_memory / max_memory)) * 100
Next
my_memory_total(i) = my_memory
Catch err As ManagementException
'Console.WriteLine("An error occurred while querying for WMI data: " & err.Message)
End Try
'On va rechercher la valeur de la charge du cpu
Try
Dim searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_Processor")
For Each queryObj As ManagementObject In searcher.Get()
my_cpu_load = (queryObj("LoadPercentage"))
my_cpu_frequency_max = (queryObj("MaxClockSpeed"))
my_cpu_frequency_use = (queryObj("CurrentClockSpeed"))
my_cpu = ((my_cpu_load * my_cpu_frequency_use) / my_cpu_frequency_max)
Next
my_cpu_total(i) = my_cpu
Catch err As ManagementException
'Console.WriteLine("An error occurred while querying for WMI data: " & err.Message)
End Try
Thread.Sleep(60000)
'On va rechercher la valeur du nom du serveur(ComputerName)
Try
Dim searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_OperatingSystem")
For Each queryObj4 As ManagementObject In searcher.Get()
my_server = (queryObj4("CSName"))
Next
Catch err As ManagementException
'Console.WriteLine("An error occurred while querying for WMI data: " & err.Message)
End Try
'On se connecte à la Db
Try
VDLB_VAR.Connect(SQL_server, SQL_userid, SQL_password, SQL_DATABASE)
Catch ex As Exception
'Console.WriteLine(ex.Message)
End Try
If (VDLB_VAR.ConnectionStatus) Then
'On va rechercher la valeur de la mémoire physique disponible et la mémoire physique total, et on ressort le pourcentage utilisé par exemple 49
Try VDLB_VAR.MySQL_Query("UPDATE vdlb_perf SET memory '" & my_memory & "' , cpu '" & my_cpu & "' WHERE server='" + my_server + "'")
VDLB_VAR.CloseClass()
Catch ex As Exception
'Console.WriteLine(ex.Message)
End Try
Else
Console.WriteLine("Erreur SQL")
Thread.Sleep(300000)
End If
Loop While boucle = "s"
End Sub
End Class
Si qqun a une idée sur la chose ? car j'ai des codes fesant 10 x cette taille là et prenant même pas 700ko en mémoire.
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 8 mars 2008 à 10:10
Problèmes d'objets créer et non détruit.
Pour commencer ceci :
Dim i As Integer
For i = 0 To 4
à chauqe tour de ta boucle Do, tu crée une variable i, qui ne te sert que dans la boucle For, la précédente n'étant pas forcément détruite. Utilise plutot ceci, ta variable i sera automatiquement marquée libérable à la fin de la boucle For
For i As Integer = 0 To 4
Ensuite pour Searcher, tu crée les objets, mais jamais tu ne les détruits.
Essaye peut-etre d'encadrer ton code utilisant l'objet dans un Using, l'objet créé par le using étant automatiquement détruit à la fin du Using :
Using searcher As New ManagementObjectSearcher( _
"root\CIMV2", _
"SELECT * FROM Win32_Processor")
For Each queryObj As ManagementObject In searcher.Get()
my_cpu_load = (queryObj("LoadPercentage"))
my_cpu_frequency_max = (queryObj("MaxClockSpeed"))
my_cpu_frequency_use = (queryObj("CurrentClockSpeed"))
my_cpu = ((my_cpu_load * my_cpu_frequency_use) / my_cpu_frequency_max)
Next
my_cpu_total(i) = my_cpu
End Using
Si le using ne marche pas, mais simplement un searcher=Nothing juste avant le Catch
Rien que ça devrai, je pense amélioré un peu les choses.
Info : En .Net, la libération de la mémoire est à la charge du Garbage Collector. Elle n'est pas forcément instantanée.
laurent207
Messages postés101Date d'inscriptionjeudi 31 janvier 2002StatutMembreDernière intervention11 avril 2008 31 mars 2008 à 13:08
bonjour,
J'ai le même problème que toi, mon appli qui tourne comme service windows augmante sans arrêt en mémoire.
Elle commence à 36Mo et augmante progressivement et constament. Alors j'ai lu sur des forum qu'une appli .net démarre en utilisant environ 30Mo. Donc, si la tienne prend que 20Mo c'est bien, mais augmente-t-elle en mémoire ?
dimitriusai
Messages postés76Date d'inscriptionlundi 6 novembre 2006StatutMembreDernière intervention 7 mai 20091 31 mars 2008 à 13:47
Après une optimisation, comme expliquée ci dessus, et surtt l'utilisation du garbage collector, j'ai réussi à stabiliser l'utilisation mémoire à 17mo, et le logiciel tourne depuis 3 semaines sans problème et augmentation en ram.
laurent207
Messages postés101Date d'inscriptionjeudi 31 janvier 2002StatutMembreDernière intervention11 avril 2008 11 avril 2008 à 12:39
est-ce que je peux voir ton code, stp.
pour chaque objet (integer, string, ping, searcher, ldap ou autre), j'ai mit une .dispose et objet=nothing, dés que j'en ai plus bessoin. J'ai aussi fait un for i as integer, mais ça na pas l'air de marcher. Maintenant au lieu de monter à 600Mo, je monte à 70Mo au bout de 2 jours.
laurent207
Messages postés101Date d'inscriptionjeudi 31 janvier 2002StatutMembreDernière intervention11 avril 2008 11 avril 2008 à 13:35
c'est une parti, y a environ 5000 lignes
Private Sub Commencer()
Dim str_AdresseIPDuPoste As String = String.Empty
Dim str_NumDuPoste As String = String.Empty
Dim b_Prioritaire As Boolean = False 'booléen pour forcer l'inventaire du poste
Dim int_IDPoste As Integer = 0 'correspond à l'id du poste dans la bd
Dim b_Ancien As Boolean = False 'booléen pour savoir si l'inventaire est ancien
Dim b_Ping As Boolean = False
Dim tab_ListOrdi() As String
Dim int_NbOrdiRestant As Integer = 0
Dim obj_DateLog As Date = System.DateTime.Today
While True 'boucle infinie car le service tourne à l'infini ^^
Dim int_NbPosteInventorie As Integer = 0
tab_ListOrdi = Nothing
Dim tab_ListOrdiTmp As New Collections.Generic.List(Of String)
'AD(fw2)
Dim Ldap As New DirectoryEntry("LDAP://nom_du_domaine_AD")
'Création un filtre sur l'objet computer
Dim searcher As DirectorySearcher = New DirectorySearcher(Ldap)
searcher.Filter = "(objectCategory=Computer)"
searcher.PageSize = 4000
Try
For Each result As SearchResult In searcher.FindAll
'on récuprer les noms des pc
Dim DirEntry As DirectoryEntry = result.GetDirectoryEntry
Dim nom As String = String.Empty
'nom = DirEntry.NativeObject.ToString
If Not (DirEntry.Properties("cn").Value Is Nothing) Then
nom = DirEntry.Properties("cn").Value.ToString()
'on redimensionne le tableau pour y insérer le poste trouvé dans AD
ReDim Preserve tab_ListOrdi(int_NbOrdiRestant)
tab_ListOrdi(int_NbOrdiRestant) = nom
int_NbOrdiRestant += 1
End If
DirEntry.Dispose()
DirEntry = Nothing
nom = Nothing
Next result
Catch ex As Exception
str_Error = "37;" & str_NumDuPoste & ";erreur lors de la récupération de la liste des postes sur AD (" & ex.Message.ToString & ")"
log.Fatal(str_Error)
JEventLog.WriteEntry("Erreur lors de la récupération de la liste des postes sur AD (" & ex.Message.ToString & ")", EventLogEntryType.Warning)
Thread.Sleep(1800000) '30mn
End Try
searcher.Dispose()
searcher = Nothing
Ldap.Close()
Ldap.Dispose()
Ldap = Nothing
'affiche le nombre total de poste (voisinage réseau + AD)
int_NbOrdiRestant = tab_ListOrdi.GetLength(0)
str_Error = "99;" & str_NumDuPoste & ";nombre de postes trouvé : " & int_NbOrdiRestant.ToString
'on parcourt le tableau (l'indice commence à 0, donc on enléve 1 au nombre total de poste)
For i As Integer = 0 To int_NbOrdiRestant - 1
BD.Connexion()
Try
'recharge les paramètres du fichier de config XML car on peut les avoir modifiés
Nom_du_service.My.Settings.Reload()
'On récupère le num d'inventaire du poste à partir de son adresse IP
str_NumDuPoste = ""
str_NumDuPoste = RecupNum(str_AdresseIPDuPoste).Trim
'cherche si le nom du poste est dans la base de données
Dim b_Existe As Boolean = False b_Existe BD.Existe("SELECT * FROM Poste WHERE NumInventaire " & Chr(34) & str_NumDuPoste & Chr(34))
If (Not b_Existe) Then
'il n'existe pas dans la base de données
'on ping le poste
b_Ping = False
b_Ping = PingFW2(str_AdresseIPDuPoste)
If (b_Ping) Then
'pour pas dépasser la taille du champs dans access
str_NumDuPoste = Microsoft.VisualBasic.Left(str_NumDuPoste, 20)
BD.AjouterPoste("SELECT * FROM Poste", "NumInventaire", str_NumDuPoste, True)
BD.AjouterPoste("SELECT * FROM Poste WHERE NumInventaire = " & Chr(34) & str_NumDuPoste & Chr(34), "Prioritaire", "True", False)
BD.AjouterPoste("SELECT * FROM Poste WHERE NumInventaire = " & Chr(34) & str_NumDuPoste & Chr(34), "DateMajFiche", System.DateTime.Today.ToString, False)
b_Existe = True
End If
End If
If (b_Existe) Then
'Récupère le champs "IDPoste" de la table "Poste" int_IDPoste BD.ReturnID("SELECT * FROM Poste WHERE NumInventaire " & Chr(34) & str_NumDuPoste & Chr(34))
'Si l'inventorisation du poste est inférieur au cycle
Dim obj_Cycle As New TimeSpan(CInt(My.Settings.Cycle_inventaire), 0, 0, 0, 0)
If (CDate(BD.ReturnDate("SELECT * FROM Poste WHERE IDPoste = " & int_IDPoste)) < (System.DateTime.Today() - obj_Cycle)) Then
'l'inventaire du poste est ancien
b_Ancien = True
Else
'l'inventaire du poste n'est pas ancien
b_Ancien = False
'si prioritaire, on force l'inventaire b_Prioritaire BD.EstPrioritaire("SELECT * FROM Poste WHERE IDPoste " & int_IDPoste)
If (b_Prioritaire) Then
b_Ancien = True
'lbl_Forcer.Text = ""
End If
End If
obj_Cycle = Nothing
If (b_Ancien) Then
'on ping le poste
b_Ping = False
b_Ping = PingFW2(str_AdresseIPDuPoste)
If (b_Ping) Then
'on ajoute la date du ping
BD.AjouterPoste("SELECT * FROM Poste WHERE IDPoste = " & int_IDPoste, "DatePing", System.DateTime.Today.ToString, False)
'vérifie si le poste est au moins sous Windows 2000 et qu'on ai accés au c$
If (Poste2k(str_AdresseIPDuPoste)) Then
'répare le WMI et execute un script vbs
b_WMIOk = RepareWMI(str_AdresseIPDuPoste, str_NumDuPoste)
If (Not b_WMIOk) Then
'on essaye de récupérer le numèro de serie par DMI
str_Error = "45;" & str_NumDuPoste & ";impossible de réparer WMI automatiquement (intervention manuel requise)"
log.Warn(str_Error)
End If
'vérifi si on peut se connecter au registre distant
Try
Dim Ruche As RegistryKey = Nothing
If (str_AdresseIPDuPoste = "localhost") Then
Ruche = Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion")
Else
Ruche = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, str_AdresseIPDuPoste).OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion")
End If
If (Ruche.GetValue("ProductId") IsNot Nothing) Then
b_ConnexionRegistre = True
Else
b_ConnexionRegistre = False
End If
If Ruche IsNot Nothing Then Ruche.Close()
Ruche = Nothing
Catch ex As Exception
str_Error = "41;" & str_NumDuPoste & ";droits insuffisant pour se connecter à la base de registre (" & ex.Message.ToString & ")"
b_ConnexionRegistre = False
End Try
If (b_ConnexionRegistre) Then
'Inventaire_du_poste(str_AdresseIPDuPoste, str_NumDuPoste, int_IDPoste)
BD.AjouterPoste("SELECT * FROM Poste WHERE IDPoste = " & int_IDPoste, "Prioritaire", "False", False)
int_NbPosteInventorie = int_NbPosteInventorie + 1
End If
End If
End If
b_Ping = Nothing
End If
b_Ancien = Nothing
End If
b_Existe = Nothing
int_IDPoste = Nothing
b_WMIOk = Nothing
b_ConnexionRegistre = Nothing
Catch ex As Exception
str_Error = "37;" & str_NumDuPoste & ";erreur inconnue dans le module général c'est produite (" & ex.Message.ToString & ")"
Debug.Print(str_Error)
End Try
'affiche le nombre d'ordi restant
If (int_NbOrdiRestant > 0) Then int_NbOrdiRestant = int_NbOrdiRestant - 1
'ferme la connexion à la base de données et supprime les objets en mémoire
BD.Deconnexion("olex_BD")
'vérification de la date à la fin de la boucle pour faire un traitemant journalier
If (System.DateTime.Today > obj_DateLog) Then
obj_DateLog = System.DateTime.Today
End If
End While
End Sub
Private Function PingFW2(ByVal str_AdresseIPDuPoste As String) As Boolean
' AdresseIP : chaîne de caractère contenant l'adresse IP de l'hôte à "pinger"
Dim b_resultatPing As Boolean = False
Dim PingOpt As New PingOptions(64, True)
Dim bt_buffer As Byte = 0
Dim obj_Ping As New Ping
' Objet PingReply qui nous permettra de récupérer le résultat
Dim obj_ReponsePing As PingReply
Try
' Instanciation d'un objet Ping
' Récupération du résultat obtenu par la méthode Send()
obj_ReponsePing = obj_Ping.Send(str_AdresseIPDuPoste, 1000) ', bt_buffer, PingOpt)
' Formatage du résultat avec récupération du temps en millisecondes
' grâce à la propriété RoundtripTime.
Select Case obj_ReponsePing.Status
Case IPStatus.Success
b_resultatPing = True
Case IPStatus.TimedOut
b_resultatPing = False
Case Else
b_resultatPing = False
End Select
Return b_resultatPing
b_resultatPing = Nothing
End Function
voici une fonction qui utilise du wmi :
Public Shared Function Marque(ByVal str_AdresseIPDuPoste As String, ByVal str_NumDuPoste As String, ByVal int_IDPoste As Integer) As Boolean
Dim b_Marque As Boolean = False
Dim str_Manufacturer As String = String.Empty
Try
Dim searcher As New ManagementObjectSearcher("\" & str_AdresseIPDuPoste & "\root\CIMV2", "SELECT * FROM Win32_ComputerSystem")
Dim info As ManagementObject = Nothing
For Each info In searcher.Get()
str_Manufacturer = info("Manufacturer").ToString
'pour pas dépasser la taille du champs dans access
str_Manufacturer = Microsoft.VisualBasic.Left(str_Manufacturer, 60)
BD.AjouterRow("SELECT * FROM Poste WHERE IDPoste = " & int_IDPoste, "Poste", "Marque", str_Manufacturer, int_IDPoste, False)
Next
b_Marque = True
info.Dispose()
info = Nothing
searcher.Dispose()
searcher = Nothing
Catch ex As Exception
str_Error = "11;" & str_NumDuPoste & ";erreur WMI (Materiel.Marque)"
b_Marque = False
End Try