neologix a écrit 346 commentaires

  • [^] # Re: free n'est pas fiable

    Posté par  . En réponse au message Utilisation de la RAM. Évalué à 4.

    Pour savoir ce qui est réellement alloué, il faut regarder Committed_AS.

    Après, la différence est déjà dans la mémoire inactive: il s'agit probablement de process qui ont fait des mmap, soit file-backed read-only (donc pas besoin de swapper pour réclamer), soit anonymous mais pas encore écrit dedans (donc pas non plus besoin de swapper pour réclamer), et après quelque temps, le noyau les a dégagés de la RAM pour faire de la place pour le page cache (le degré dépend de la swapinness). Du coup ils n'apparaissent pas dans RSS, mais sont toujours pris en compte par free.

    J'ai aussi déjà eu des cas où, en ext3 monté avec data=ordered, supprimer un fichier déjà ouvert va laisser les entrées correspondantes dans le page cache, du coup ils apparaissent en inactive dans /proc/meminfo, free les rapporte toujours, mais on ne voit évidemment rien dans ps.

    En gros, tant que ton Committed_AS n'augmente pas, pas de souci…

  • # free n'est pas fiable

    Posté par  . En réponse au message Utilisation de la RAM. Évalué à 2.

    Mais pas du tout.
    Que donnent:

    free -m
    
    

    et

    cat /proc/meminfo
    
    
  • [^] # Re: Ai-je bien compris ?

    Posté par  . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 2.

    Donc, pris en compte par le cpu ayant écrit mais pas les autres ?

    Et oui, d'où l'utilité des barrières.

    J'avais lu qu'il relachait sans cesse la cohérence mémoire, et l'itanium allait assez loin, mais je ne pensais pas à ce point-là.

    La performance est à ce prix.

    Pour vraiment s'amuser, il y a l'architecture alpha, qui peut réordonner les "dependant reads". Donc en gros, quand tu parcours une liste chaînée, tu peux récupérer une valeur non initialisée dans ton noeud: il faut une read barrier même pour lire une iste chainée ;-)

  • [^] # Re: Ai-je bien compris ?

    Posté par  . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 2.

    Non, à cause des store buffers et invalidate queues, il y a besoin de memory barriers:
    http://en.wikipedia.org/wiki/Memory_barrier

    Ou mieux la référence :
    https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html

  • [^] # Re: Ai-je bien compris ?

    Posté par  . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 3.

    Ma question est plus poussé, c'est "Est ce que le fait que GCC/Clang ne remplace pas cela par une boucle infinie est un comportement documenté/standard/… et si oui pourquoi ?".

    Non, ce n'est pas standard, mais c'est plutôt une limite de l'optimisation faite par GCC.

    Si ta variable n'est pas volatile, le compilateur peut tout à fait hoister la lecture.

    Le problème c'est que si tu as une variable globale - notamment non statique - et que dans ta boucle tu fais:

    variable = 0;

    while (variable) {
    foo(autre_variable);

    }

    et que GCC ne peut pas prouver que foo(autre_variable) ne modifie pas variable, il va forcer un reload.

    Par contre si tu appelles une fonction pure, il y a des chances que GCC ne fasse pas le reload.

    Si jamais il est fait référence à la variable running avant la boucle pour un appel de fonction ou autre, GCC génère tout de même le read, même sans volatile.

    Essaie d'appeler une fonction static.

    Ton volatile ne servira pas à grand chose : rien ne garanti que la lecture ne se fera pas dans un cache ou un write buffer pas flushé. cf. le lien "volatile considered harmfull" que j'ai posté dans un autre commentaire.

    En pratique dans ce genre de boucle tu souvent toujours des syscalls/instructions qui vont provoquer une memfence (du genre un mutex ou opération atomique sur une autre variable). Sinon, en l'absence de telles instructions, en effet dans un cas simple comme au dessus ça ne suffit pas à le garantir.
    Mais en pratique dès qu'un thread fait un appel système, context switch ou est schedulé sur un autre core, c'est équivalent à une memory barrier.

  • [^] # Re: Ai-je bien compris ?

    Posté par  . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 3.

    Je m'explique, le qualifier volatile en c/c++ n'est utile que pour des mappings hardware (genre device mapppé, ou interruption, …), mais il ne change RIEN pour l'atomicité des opérations, mais il empêche le compilateur d'optimiser certains traitements.

    Pour l'atomicité non, mais comme tu l'as dit, ça force le compilateur à faire des fetch/store, et ça peut être utile dans un contexte multi-threadé.

    Il y a par exemple cette macro utilisée pas mal dans le kernel:
    #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))

    cf https://lwn.net/Articles/508991/

    Ca ne garantit pas que tu liras la valeur la plus récente écrite (pas de memfence contrairement au volatile de java), mais tu la liras éventuellement.
    Aussi, ça garantit que la variable ne sera lue qu'une fois (sinon le compilo pourrait la dégager des registres et la relire plus tard).

    Et ça c'est utile. Idem pour les écritures.

    Après, il est vrai que dans 99% des cas, un volatile dans un code multi-threadé est mauvais signe (d'où le fameux poste de Linus "volatile considered harmful"), mais utilisé à bon escient, si ça t'évite une memfence ou une instruction atomique, ça peut être un gain non négligeable.

  • [^] # Re: Multicast

    Posté par  . En réponse au message Cherche protocole P2P inverse à BitTorrent. Évalué à 3.

    On utilise murder au boulot, et ça marche très bien:

    benchmark

    Par contre j'ai dû fait un peu de tuning pour optimiser le temps de distribution, il faudra que je remonte mes patches un de ces jours…

  • # premature optimization is the root of all evil

    Posté par  . En réponse au message Compilateur "streamé". Évalué à 7. Dernière modification le 25 mars 2013 à 10:27.

    Est-ce que y a des grosses failles qui font que c'est de la grosse merde?

    Bah déjà, pour peu que ton makefile soit bien fait, tu ne vas pas tout recompiler à chaque fois, seulement le différentiel.

    Ensuite, j'ai un doute sur le fait que la création des process pèsent lourd face à la phase de compilation.

    Par exemple, voilà le résultat d'un benchmark d'une compilation clean de Python :

    time :

    real    1m36.857s
    user    1m28.322s
    sys     0m6.429s
    
    

    strace -c -f :

    % time     seconds  usecs/call     calls    errors syscall
    ------ ----------- ----------- --------- --------- ----------------
     99.29   41.756190        9054      4612      1679 wait4
      0.27    0.112962          21      5259      3232 execve
      0.10    0.041814          20      2108           clone
      0.07    0.028498           1     55672           write
      0.05    0.022086           0     92638           read
      0.04    0.015907           0    114234     66266 open
      0.04    0.015722         114       138           rename
      0.04    0.015164          14      1106       201 unlink
    
    

    La grosse majorité est passé en userland, et le reste contient les I/O, etc. Donc fork()/exec() & Co ne pèsent pas lourd, sans compter que dans ton approche il y aurait aussi beaucoup d'IPC qui n'est pas gratuit non plus…

  • [^] # Re: lire l'aide de Maven et appliquer les conseils fournis dans la liste des erreurs

    Posté par  . En réponse au message Compilation de code source opennms 1.10.8. Évalué à 3.

    Dans ce lien pour JavaSE7 http://docs.oracle.com/javase/7/docs/api/javax/sql/CommonDataSource.html ,l'interface CommonDataSource contient la méthode getParentLogger or pour JavaSE6 on la trouve pas http://docs.oracle.com/javase/6/docs/api/javax/sql/CommonDataSource.html

    Tout est dit.
    L'interface CommonDataSource a gagné une méthode avec Java 1.7: comme la classe C3P0ConnectionFactory ne l'implémente pas, ça pète.

    La raison est très simple, tu utilises JDK 1.7 alors qu'opennms n'a pas été porté dessus. Utilise JDK 1.6, et ça devrait rouler.

  • [^] # Re: intéressant

    Posté par  . En réponse au journal wait4: attendre la fin d’un ou plusieurs processus quelconques . Évalué à 4.

    C’est le comportement voulu

    Oula je plane, en effet.

    Sinon, deux autres remarques :
    - la version avec polling a une race, si jamais le PID est recyclé entre deux polling. Une alternative serait par exemple d'ouvrir /proc//status, et de faire un read() régulièrement: si jamais le processus est mort entre temps, tu vas prendre ESRCH. Mais bon, ce n'est pas portable, et il y a déjà netlink pour Linux.
    - le socket netlink reçoit un message par fork()/exec()/exit(), pour tous les process sur la machine: s'il beaucoup de process sont créés, le socket buffer risque de se remplir.
    Démo:

    shell 1:

    $ while [ 1 ]; do /bin/false; done
    
    

    shell 2:

    # nice -n 19 strace ./wait4 1
    [...]
    recv(3, "L\0\0\0\3\0\0\0\261\252\t\0\0\0\0\0\1\0\0\0\1\0\0\0\261\252\t\0\0\0\0\0"..., 76, 0) = 76
    recv(3, "L\0\0\0\3\0\0\0\262\252\t\0\0\0\0\0\1\0\0\0\1\0\0\0\262\252\t\0\0\0\0\0"..., 76, 0) = 76
    recv(3, 0xbfa7a324, 76, 0)              = -1 ENOBUFS (No buffer space available)
    
    

    Tu devrais pouvoir mettre en place un filtre pour ne recevoir que les notifications d'intérêt, c'est pas trivial (BPF) mais ça peut être intéressant ;-)

  • # intéressant

    Posté par  . En réponse au journal wait4: attendre la fin d’un ou plusieurs processus quelconques . Évalué à 10.

    Intéressant !

    Quelques remarques :

    Ca ne fonctionnait pas sur ma bécanne, voilà un patch :

    --- src/wait4pid.c.orig 2013-03-21 14:20:12.000000000 +0100
    +++ src/wait4pid.c      2013-03-21 14:33:13.129854021 +0100
    @@ -43,6 +43,8 @@
         } *payload;
         char buf[NLMSG_SPACE(sizeof(struct payload_t))];
    
    +    memset(buf, 0, sizeof(buf));
    +
         hdr = (struct nlmsghdr *)buf;
         hdr->nlmsg_type = NLMSG_DONE;
         hdr->nlmsg_flags = NLM_F_REQUEST;
    @@ -52,6 +54,7 @@
         payload = (struct payload_t *) NLMSG_DATA(hdr);
         payload->msg.id.idx = CN_IDX_PROC;
         payload->msg.id.val = CN_VAL_PROC;
    +    payload->msg.len = sizeof(payload->op);
         payload->op = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE;
    
         return send(sock, hdr, NLMSG_SPACE(sizeof(*payload)), 0);
    
    

    Il y a un problème dans le cas où netlink n'est pas supporté et on passe le PID d'un process auquel on ne peut pas envoyer de signal: EPERM est retourné par kill(), et wait4 ne va jamais retourner.

    static void
    on_alarm(int sig)
    {
        exit(EXIT_SUCCESS);
    }
    
    

    Un signal handler doit être async-signal safe, en gros réentrant.
    Et exit() ne l'est pas, contrairement à _exit(), notamment puisqu'il appelle les callbacks enregistrés avec atexit().

    Là tu n'as pas vraiment de risque de deadlock/crash normalement, mais écrire du code exécutant dans le contexte d'un signal handler est subtil, par exemple :
    ```
    static void
    wait4pid_close(void)
    {
    if ( listener_set ) {
    set_proc_listen(sock, 0);
    listener_set = 0;
    }

    if ( sock ) {
        close(sock);
        sock = 0;
    }
    
    

    }
    ```

    Les variables listener_set et sock devraient être volatile (elles pourraient aussi être static).

    La façon propre de faire serait d'utiliser select() sur ton socket, pour sortir lorsque le timeout est atteint.

    Enfin c'est un détail.

    Sinon :

    ec = payload->evt.event_data.exit.exit_code / 256;

    Tu peux utiliser WEXITSTATUS().

    Dans set_proc_listen, tu ne retry pas sur EINTR (peu probable).

  • [^] # Re: Magic SysRq

    Posté par  . En réponse à la dépêche Infection par rootkit « SSHd Spam » sur des serveurs RHEL/CentOS. Évalué à 10.

    simulate a hard powercut to ensure the rootkit cannot reroot if it's memory resident.

    En même temps, si on ne sait pas lire…

  • [^] # Re: Normal

    Posté par  . En réponse au message recherche trolleur de compétition. Évalué à 2.

    par exemple, le fait que l'UE aurait interdit aux carioles roumaines de circuler

    Je ne sais pas qui est à l'origine de cette décision, mais c'est vraiment une bonne idée, parce qu'entre ça et les chiens errants, c'est vraiment chaud la conduite en Roumanie (surtout de nuit, parce que les carrioles n'ont pas de dispositifs rétro-réfléchissants)…

  • [^] # Re: tcpdump, topologie? - WiFi, FAIbox merdique ?

    Posté par  . En réponse au message connexion réseau bizarre. Évalué à 2.

    je viens de faire tcpdump sur l'interface "any" et comme je m'y attendais, comme on est sur la même machine , on ne vois aucun paquet passer :'(

    Non, même si c'est sur la même machine, ce n'est pas normal.

    Que renvoient
    ip6tables -L

    et
    route -n

    Tu arrives à pinger ?

  • # tcpdump, topologie?

    Posté par  . En réponse au message connexion réseau bizarre. Évalué à 2.

    Déjà un tcpdump sur la machine cible te permettra de voir si le SYN arrive.
    Ensuite, tu ne précises pas: tu as un switch, un routeur, une box?
    Non parce que ça ressemble furieusement à un paquet droppé entre les deux…

  • [^] # Re: regarde si tu ne peux pas faire une simple recherche

    Posté par  . En réponse au message Optimisation programme. Évalué à 3.

    Il y a os.walk() pour ça. Il faut utiliser fnmatch pour matcher les noms de fichiers, os.walk() ne le supporte pas.
    Sinon il y a WalkDir de Nick Coghlan (core dev Python) qui est pas mal.

    Mais ça ne devrait pas accélérer, ça sera toujours O(nombre de fichiers à traiter) (en fait O(nombre de fichiers dans l'arborescence), mais le facteur dominant est le traitement des fichiers).

    Sinon, j'imagine que faire un commit à chaque requête n'est pas optimal, tu devrais pouvoir te contenter de le faire à la fin (dans closeDB).

  • # SIGHUP

    Posté par  . En réponse au message Kill d'un processus et processus fils. Évalué à 6.

    Dans le cas général, lorsqu'un processus se termine, cela se passe très simplement :
    - ses processus fils sont reparentés à init
    - ils continuent leur vie, et lorsqu'ils meurent init effectue le waitpid()

    Mais dans ton cas, c'est un peu plus complexe, à cause du tty. Lorsque le shell se termine :
    - comme le shell "controllait" le tty (controlling process, session leader), le noyau (le driver tty) envoie un SIGHUP à tous les process dans le foreground group. C'est ce signal qui provoque la terminaison des processus. Mais ce signal peut être ignoré, par exemple avec sighup, ou on peut carrément lancer les process dans une nouvelle session et sans controlling tty avec setsid.

    Notes :
    Dans tous les cas, ce n'est pas le shell lui-même qui tue les processus fils.
    C'est en fait bien plus complexe sous POSIX, mais les process groups, sessions, etc…

    Pour le minimum à savoir, tu peux voir ici : http://www.win.tue.nl/~aeb/linux/lk/lk-10.html

  • # donc en gros

    Posté par  . En réponse au message Obligé d'utiliser un système de fichier propriétaire ?. Évalué à 6.

    Les seuls systèmes de fichier supportés par des systèmes propriétaires sont des systèmes de fichier propriétaires ? Étonnant, non ?

    Plus sérieusement, tu as par exemple des formats standards comme ISO 9660 ou UDF (i.e. supports optiques, pas pour disque dur/clé USB). Sinon, un montage NFS/CIFS.

  • [^] # Re: record bidon

    Posté par  . En réponse à la dépêche OpenBSD 5.2. Évalué à 2.

    Heu, c'est pas vrai, Debian t'installe exim et le démarre.
    Je crois qu'il est configuré pour écouter sur 127.0.0.1 mais ça fait quand même un service réseau qui tourne.

    C'est faux, si tu n'effectues pas l'étape de sélection des paquets après l'installation du système de base, exim n'est pas installé. Je n'ai pas de MTA, sur aucune de mes 3 machines.

    Ensuite c'est un peu fort de parler de marketing pour un projet qui n'a rien à vendre.

    Marketing, affirmation fallacieuse, peu importe le terme.

  • [^] # Re: record bidon

    Posté par  . En réponse à la dépêche OpenBSD 5.2. Évalué à 3.

    Une installation de Debian par défaut (comprendre sélection uniquement des paquets de base) ne démarre aucun service, pas même ssh. Ce "record" est donc du pur marketing, et ne présage en rien de la sécurité du système (que je ne remets pas en cause, il y a un gros travail derrière).

  • # record bidon

    Posté par  . En réponse à la dépêche OpenBSD 5.2. Évalué à 1.

    We remain proud of OpenBSD’s record of more than ten years with only two remote holes in the default install
    
    

    Je vais me faire traiter de troll, mais pour moi cette affirmation est bidon.
    Parce qu'il s'agit de failles exploitables à distance dans une installation qui ne démarre que le serveur ssh.
    Je suis curieux de savoir combien de telles failles, à configuration identique, ont connu la plupart des distributions Linux.

  • [^] # Re: En parlant de TCP...

    Posté par  . En réponse à la dépêche MPTCP, TCP dans un monde ultra‐connecté. Évalué à 6.

    Oui, enfin uniquement sur des réseaux wifi (802.11 and co), il faut le préciser…
    C'est bien connu que TCP pose problème sur les réseaux sans-fil, c'est d'ailleurs pour cela qu'il y a dans 802.11 un mécanisme de retransmission au niveau LLC qu'il n'y a pas pour ethernet.
    Le wifi c'est juste pourri, avec un peu de chance ça disparaîtra avec la 4G et la femto.

  • [^] # Re: Hum

    Posté par  . En réponse au journal Les sémaphores. Évalué à 3.

    Attention, sémaphore binaire et mutex ne sont pas exactement identiques, du moins sous POSIX.
    Un mutex ne peut être déverrouillé que par le thread qui l'a verrouillé, alors que n'importe quel process/thread peut faire un up sur une sémaphore. Ca permet par exemple d'implémenter simplement un rendez-vous point.
    Les locks Python sont des sémaphores binaires, pas des mutex.

  • # barrière

    Posté par  . En réponse au journal Les sémaphores. Évalué à 4.

    Ce que tu implémentes ici, c'est ce qu'on appelle une barrière.
    C'est disponible pour les threads POSIX avec pthread_barrier_init()/pthread_barrier_wait(), mais pas pour les IPC.
    Sous Python, le module multiprocessing supporte les barrières inter-process, par exemple.

  • # votre/vôtre

    Posté par  . En réponse au sondage Votre nationalité...?. Évalué à 7.

    "votre nationalité"
    "la vôtre"

    Par ailleurs, puisqu'il s'agit de l'adjectif, on écrit "nationalité française", sans majuscule. Mais on écrit "Les Françaises…".