Faire un don ! | | style | statistiques | contactez-nous | plan | lettre d'information

Programmation.c : Cron ou sleep() ?

Posté par Ludovic Rivallain (aka Creasy) (page perso, ) le 17 mars 2008

Bonjour,



Je me colle d'ici peu au codage d'un petit programme qui vérifiera chaque minute la correspondance entre l'heure actuelle et l'heure de réveil demandée par des utilisateurs d'un service téléphonique basé sur Asterisk (info placée dans un fichier).



J'avais déjà le même programme codé avec les pieds et en bash (vite fait, bien fait fonctionnel, mais comme le nombre d'utilisateurs explose, j'ai décidé de le recoder en C (et avec les mains cette fois) pour réduire le temps d'exécution et limiter la consommation de performances.



Avant j'utilisais cron pour lancer chaque minute ce petit script.



J'en viens à ma question:

Est-il plus "performant" d'utiliser cron pour ce genre de tâche (lancer le programme toutes les minutes) ou d'utiliser un "sleep()" dans le programme (qui sera lancé en daemon du coup) avec un temps de repos variable selon le temps qu'a duré l'exécution?



(non je ne cherche pas à créer un nouveau troll cron Vs sleep() ;-) )



Et quels sont les avantages/inconvénients de ces deux solutions?



En gros si j'utilisais "sleep()" j'imagine un truc comme:

  1. Exécution du programme,
  2. Juste avant la fin on regarde qu'elle heure il est et on en déduis le temps qu'il reste jusqu'à la prochaine minute,
  3. On patient le temps calculé,
  4. On reboucle en "1".


Merci d'avance pour vos lumières.



Ludo,

> Lire le message (13 commentaires, moyenne: 2,5).  

Vous avez demandé le commentaire #914346.

cron vs sleep() ?

Posté par Obsidian () le 17/03/2008 à 14:43. (lien). Évalué à 6.

Dans les deux cas, c'est du polling et c'est à éviter chaque fois que possible. Mieux tu regardes du côté de alarm() :

man 2 alarm

Les seuls avantages de cron, c'est de ne pas lancer un nouveau daemon exprès, et surtout de ne pas laisser dormir inutilement les processus en mémoire s'ils ne servent à rien. Mais pour le reste, c'est assez sauvage. Ton application est dépendante de cron, et déclencher un truc toutes les minutes x nombre d'utilisateurs, tu risques de le sentir passer. Ton crond va gagner des places en temps cpu cumulé.

Moi je partirai quand même sur un daemon dédié. Moins lourd, plus fiable. Ensuite, c'est de la conception : tu ne te réveilles pas toutes les minutes pour voir si c'est l'heure, mais à la place, tu prends les directives de tous les users, tu les tries par ordre chronologique, tu calcules le nombre de seconde entre l'instant présent et le premier de la liste, tu te mets en attente pour cette durée exacte, tu fais ce qu'il y a à faire et tu recommences avec l'entrée suivante.

Pour ce faire, tu peux effectivement faire un sleep(), mais tu seras réveillé au moindre signal (notamment celui de alarm()), donc il faudra pendre cela en charge. Mieux : tu crées un socket et tu l'écoutes avec select() dans une boucle principale. De cette manière, tu es sûr de ne pas te réveiller sans raison valable et tu peux communiquer avec ton daemon quand il n'est pas occupé à autre chose. Tu n'as même pas besoin de lancer de nouveaux threads. Cerise sur le gâteau : select() accepte une valeur de timeout facultative, qui te permet de sortir de l'état d'attente au bout d'une durée fixe, même si aucun événement n'a eu lieu.

En tout état de cause, et encore une fois, évite le réveil périodique minute par minute, surtout avec un sleep (60) car tu ne sais jamais à quel moment de la minute tu vas te réveiller. Si c'est à 00h00m59s, par exemple, tu auras 59 secondes de retard et dans certains cas, cela peut être préjudiciable à l'utilisateur.

  • [^]Re: cron vs sleep() ?

    Posté par Ludovic Rivallain (aka Creasy) (page perso, ) le 17/03/2008 à 17:25. (lien). Évalué à 2.

    "Ton application est dépendante de cron, et déclencher un truc toutes les minutes x nombre d'utilisateurs, tu risques de le sentir passer"
    Heureusement je ne le déclenche qu'une fois et j'appelle via ce programme un autre pour chaque utilisateur qui a demandé un réveil à l'heure actuelle. Je n'ai donc pas plus d'une itération de ce programme à chaque minute (si cron).

    "mais à la place, tu prends les directives de tous les users, tu les tries par ordre chronologique, tu calcules le nombre de seconde entre l'instant présent et le premier de la liste, tu te mets en attente pour cette durée exacte"
    L'idée est très bonne mais implique qu'à chaque changement dans le fichier, je fasse une réorganisation de ma "liste d'attente". Ca me semble un peu plus lourd à mettre en place mais c'est beaucoup plus économe en performances.

    "évite le réveil périodique minute par minute, surtout avec un sleep (60)"
    Oui ça j'ai oublié dès la première seconde de réflexion :) c'est beaucoup trop aléatoire et à chaque itération on incrémente l'erreur... bilan... on se retrouverai assez vite avec des gens réveillés à 10h au lieu de 8h00 :s

    • [^]Re: cron vs sleep() ?

      Posté par gaaaaaAab () le 17/03/2008 à 21:37. (lien). Évalué à 2.

      L'idée est très bonne mais implique qu'à chaque changement dans le fichier, je fasse une réorganisation de ma "liste d'attente"

      joie dans la demeure ! qsort fait partie du C ansi ! \(^.^)/

      [^]Re: cron vs sleep() ?

      Posté par Obsidian () le 17/03/2008 à 21:50. (lien). Évalué à 1.

      Heureusement je ne le déclenche qu'une fois et j'appelle via ce programme un autre pour chaque utilisateur qui a demandé un réveil à l'heure actuelle. Je n'ai donc pas plus d'une itération de ce programme à chaque minute (si cron).

      C'est déjà trop, à mon avis. Et ça reste du polling.

      L'idée est très bonne mais implique qu'à chaque changement dans le fichier, je fasse une réorganisation de ma "liste d'attente". Ca me semble un peu plus lourd à mettre en place mais c'est beaucoup plus économe en performances.

      C'est comme ça que cela se passe déjà pour la plupart des daemons, notamment Apache et PostgreSQL. On envoie un signal au processus pour lui demander de relire la conf' (un outil tout fait existe en général pour le faire). Au pire, tu mets un timeout dans ton daemon pour lui demander de relire le fichier toutes les minutes, mais ça devient superflu.