2012-04-30 3 views
1

J'ai testé un exemple de code du wiki et j'ai trouvé que libdispatch allouait beaucoup de mémoire sans le libérer, à la fois sous OS X (Lion 10.7.3, Xcode 4.3.2) et Linux (compilé et installé manuellement).Problèmes de mémoire avec libdispatch

Le code crée une source de signal SIGHUP, avec un gestionnaire qui appelle 100 000 écritures dans un fichier journal. L'écriture dans un journal est mise en file d'attente dans une file d'attente série.

La première exécution montre l'utilisation normale de la mémoire (8-9 MiB Linux et OS X). Après l'envoi d'un "kill -1", l'utilisation de la mémoire augmente de 1 à 20 Mo à chaque fois que j'envoie le signal SIGHUP.

J'ai essayé de compiler avec -fobj-arc et sans lui, mais le résultat est le même. J'ai enlevé l'utilisation de NSString dans la fonction de br_log, mais la fuite n'est pas là: c'est quelque part dans libdispatch.

J'ai essayé valgrind et Xcode Instruments, mais aucune fuite n'a été détectée. Merci d'avance,

// 
// main.m 
// test02 
// 
// Created by Aldrin Martoq on 4/29/12. 
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. 
// 

#include <unistd.h> 
#import <Foundation/Foundation.h> 
#import <dispatch/dispatch.h> 

static FILE *log_file = NULL; 
static NSString *log_filename = @"/tmp/br.log"; 
static dispatch_queue_t log_queue; 


void br_log(NSString *format, ...) { 
    @autoreleasepool { 
     va_list ap; 
     va_start(ap, format); 
     NSString *s = [[NSString alloc] initWithFormat:format arguments:ap]; 
     va_end(ap); 

     if (log_file == NULL) { 
      log_queue = dispatch_queue_create("cl.martoq.log_queue", NULL); 

      log_file = fopen([log_filename cStringUsingEncoding:NSUTF8StringEncoding], "a"); 
      NSLog(@"Log file created: %@", log_filename); 
     } 

     dispatch_async(log_queue, ^{ 
      @autoreleasepool { 
       const char *c = [s cStringUsingEncoding:NSUTF8StringEncoding]; 
       fputs(c, log_file); 
       fputs("\n", log_file); 
       fflush(log_file); 
       [s release]; 
      } 
     }); 
    } 
} 

void br_setup() { 
    signal(SIGHUP, SIG_IGN); 
    dispatch_source_t sig_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGHUP, 0, dispatch_get_main_queue()); 
    dispatch_source_set_event_handler(sig_src, ^{ 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      printf("Caught SIGHUP\n"); 
      for (int i = 0; i < 100000; i++) { 
       br_log(@"prueba: %d", i); 
      } 
     }); 
    }); 
    dispatch_resume(sig_src); 
} 


int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     // insert code here... 
     NSLog(@"Hello, World!"); 
     br_setup(); 
     dispatch_main(); 
    } 
    return 0; 
} 

Répondre

0

Comment mesurez-vous cette croissance de l'utilisation de la mémoire? Je ne peux pas le reproduire sur Mac OS X avec l'outil 'heap'.

Vous pouvez voir les effets temporaires du cache de continuation libdispatch, ce sont de petits buffers qui sont alloués pour chaque dispatch_async() et mis en cache sur une base par thread pour la vitesse. Ce cache est libéré dès la sortie d'un thread de dispatching temporaire (quelques secondes après SIGHUP dans votre exemple, sur Mac OS X au moins).

Notez également qu'il n'y a pas besoin de dispatch_async() de votre gestionnaire d'événements source puisque vous êtes déjà sur la file d'attente principale à ce moment-là (la file d'attente cible de la source)

BTW, vous avez déjà posé des questions sur ceci sur [email protected] et j'ai répondu là, s'il vous plaît ne posez pas la même question sur plusieurs forums en même temps.