Forum Programmation.c Cron ou sleep() ?

Posté par  .
Étiquettes : aucune
0
17
mar.
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,
  • # je ne vois pas l'interet

    Posté par  . Évalué à 2.

    de ton usage de sleep

    - calculer le temp qu'il reste avant la prochaine minute
    - sleep du temps qui reste
    - relancer la fonction

    mais cela peut etre efficace si ton programme met soudain plus d'une minute à s'executer (explosion du nombre d'utilisateur)

    en effet avec cron, il lancerait systematiquement ton programme toutes les minutes.

    Evidemment tu peux
    - mettre un fichier lock
    - lancer ta fonction
    - detruire le fichier lock

    c'est peut-etre plus propre que le sleep d'un temps variable...
    • [^] # Re: je ne vois pas l'interet

      Posté par  . Évalué à 2.

      Oui oui je comptais bien protéger ça un max au cas où quelque chose provoquerais un temps d'exécution plus important que la minute.

      D'après mes premiers tests une exécution dans des conditions normales ne devraient pas dépasser les quelques secondes avant d'avoir des milliers d'utilisateurs, donc je me méfie plus d'un encombrement du serveur.

      Cron n'aurait pas ce problème...
  • # Asterisk auto-dialout ! ! !

    Posté par  . Évalué à 5.

    Je te conseille de jeter un coup d'oeil là dessus:

    http://www.voip-info.org/tiki-index.php?page=Asterisk+auto-d(...)

    En gros, cela permet détablir un appel à partir d'un fichier que tu place au bonne endroit. Un petit plus de cela, c'est que si la date de dernière modification est dans le futur, ce fichier est ignoré jusqu'à cette date. A ce moment seulement, asterisk exécute les instructions de ce fichier.

    Si tu te demerde bien, tu peux facilement faire un réveil en utilisant uniquement asterisk et son extension.conf et ce pour un réveil unique ou journalier. Ainsi, pas besoin de cron, pas besoin de script extérieur. Un script AGI peut facilité la tache toutefois.

    Il y a un même un lien vers un exemple pour faire un réveil sur cette page.
    • [^] # Re: Asterisk auto-dialout ! ! !

      Posté par  . Évalué à 3.

      L'idée d'utiliser "auto-dialout" n'est pas mauvaise mais oblige à revoir d'autres choses que ce programme. Notamment l'interfaçage web.

      Toutefois, tu me fais découvrir quelque chose que je ne connaissais pas et qui peut m'intéresser à l'avenir ;-)

      Merci

      Ludo,
  • # cron vs sleep() ?

    Posté par  . É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  . É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  . É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  . É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.
  • # at ?

    Posté par  . Évalué à 2.

    > 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).

    Ce n'est pas à ça que sert la commande "at" ?
    (cf par ex http://formation-debian.via.ecp.fr/ch46.html#id2606193)
    • [^] # Re: at ?

      Posté par  . Évalué à 2.

      Ca pourrait, mais je me vois mal créer autant de tâches "at" que d'utilisateurs ayant demandé un réveil.

      100 utilisateurs = 100 tâches en attente...

      Et puis ça impliquerai de revoir d'autres choses que le programme qui fait la vérification: interface web, générateur de fichier et/ou d'enregistrement.
  • # prise de tete

    Posté par  . Évalué à 2.

    cron ou sleep ?

    aucun.

    -> man at
    c'est fait pour et ça inclus la gestion !
    • [^] # Re: prise de tete

      Posté par  . Évalué à 2.

      Même réponse que pour le message précédent.

      "at" semble approprié en effet mais il y a des contraintes (récursivité entre autres) qui sont me demanderais plus de temps à reprendre et l'interfaçage qui serait à revoir totalement.
  • # et pourquoi pas les variables conditions?

    Posté par  . Évalué à 2.

    dans les pthread tu as des variables condition :

    pthread_cond_timedwait() utilise une date absolue... pas de temps relatif comme sleep.

    avantages :
    - celà n'utilise pas de pooling... donc plus efficasse.
    - tu peut réveiller le processus en signalant la variable condition si jamais la configuration a changée (et donc vérifier ce changement a chaque réveil).

    en gros, il s'agit de fabriquer un ordonnanceur/scheduler avec une liste chainée triée... c'est franchement facile, et ce ne sont pas les exemples qui manquent en c.

    si tu veux utiliser des outils un petit peut plus haut niveau, rendre ton code un peu plus portable, tu peut utiliser la glib du projet gtk , qui n'utilise pas de dépendance a gtk cependant... tu auras juste une dépendance à la libc+glib, ce qui est acceptable, je pense.

    la fonction equivalente a celle des pthread avec la glib est :
    g_cond_timed_wait ()

    voila, amuse toi bien.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.