3 pièce(s) jointe(s)
[D10.2] Utilisation CPU excessive sur un service Windows
Bonjour à tous.
Je sèche sur un problème de CPU...
J'ai un service Windows créé avec Delphi qui fonctionne correctement pendant quelques jours (3 à 4 jours), et soudain pour une raison inconnue, l'utilisation du CPU devient assez importante.
Ce phénomène n’est pas généralisé sur tous les postes sur lesquels le service est installé.
Voici une capture qui montre l’état de mon service avant :
Pièce jointe 623791
Voici une capture de son état après quelques jours de fonctionnement :
Pièce jointe 623792
But de mon service :
Le service est destiné à enregistrer les connexions entre un programme et un serveur SQL.
Le programme envoie une demande au service et reçoit en retour une réponse du service.
De plus le service gère le contenu d'un petit fichier local.
Technique utilisée :
Pour recevoir et répondre à la demande, j’utilise le composant « TIdTCPServer », l’événement OnExecute se charge de traiter la demande ainsi :
La demande vient sous un format xml crypté, elle est stockée dans un objet dédié « TXMLCmd ».
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
|
procedure TdmServiceServer.IdTCPServerExecute(AContext: TIdContext);
var
CommandData : string;
Command : TXMLCmd;
Response : TXMLCmd;
begin
try
CommandData := AContext.Connection.Socket.ReadLn;
except
on E : Exception do
begin
if (E is EIdSilentException) then
CommandData := EmptyStr
else
raise;
end;
end;
if (CommandData <> EmptyStr) then
begin
// Chaque demande est exécutée dans un thread séparé, il faut initialiser
// COM pour pouvoir utiliser XML
CoInitializeEx(nil, COINIT_MULTITHREADED);
try
Command := TXMLCmd.Create;
Command.XMLText := Uncrypt(CommandData);
Response := TXMLCmd.Create;
try
Response.CMDId := Command.CMDId;
Response.CMDName := Command.CMDName;
try
case Command.CMDId of
CMD_CONNECT_ID :
begin
ExecConnect(Command, Response);
end;
CMD_COMP_SUB_CONNECT_ID :
begin
ExecCompSubConnect(Command, Response);
end;
CMD_DISCONNECT_ID :
begin
ExecDisconnect(Command, Response);
end;
CMD_GET_SQL_CONNECTION_DATA_ID :
begin
ExecGetSQLConnectionData(Command, Response);
end;
.
.
.
else
// Commande invalide
Response.CMDId := CMD_ERROR_ID;
Response.CMDName := CMD_ERROR_NAME;
Response.ParamAsString['Message'] := Format(rsInvalidCommand, [Command.CMDName]);
end;
AContext.Connection.Socket.WriteLn(Crypt(Response.XMLText));
finally
Response.Free;
end;
finally
Command.Free;
end;
finally
CoUnInitialize;
end;
end;
end; |
Rien de bien méchant...
Mis à part quelques boucles "for", rien de spécial, rien qui bloque son fonctionnement, mais une consommation CPU étrange.
Après toutes une série d'analyses, de log, je tombe sur un élément suspect, les « threads » utilisés.
Au démarrage du service, les threads sont au nombre de 8. Ensuite, ce nombre monte et redescend de 8 à 9 à 8. Mais à un certain moment, ce nombre de threads monte et ne redescend pas…
Par exemple, dans ma deuxième image, le nombre de Threads est à 11 et le CPU à 33.
J'ai commencé à m'intéresser à ces Threads, mais c'est un sujet que je ne maîtrise pas vraiment.
Dans Delphi, après avoir attaché le service depuis Delphi, j'ai une liste de Threads qui ressemble à ça :
Pièce jointe 623790
Du coup, je voulais essayer d'identifier ce que font ces Threads.
Mais comment ?
Il y a la colonne "Location", comment je peux savoir quelle est le code attaché derrière cette info ?
Ensuite, vu que ces "Threads" semblent augmenter, y a t-il un moyen depuis Delphi, à l'intérieure de ma programmation du service, de lister ces threads et de connaître le code exécuté ?
Merci.