web-dev-qa-db-fra.com

Comment limiter la taille du tas?

J'écris parfois des programmes Python qui sont très difficiles à déterminer la quantité de mémoire qu'il utilisera avant son exécution. En tant que tel, j'invoque parfois un programme Python qui tente d'allouer des quantités massives de RAM, ce qui provoque une permutation importante du noyau et une dégradation des performances des autres processus en cours d'exécution.

Pour cette raison, je souhaite limiter la quantité de mémoire qu'un tas Python peut augmenter. Lorsque la limite est atteinte, le programme peut simplement planter. Quelle est la meilleure façon de faire cela? 

Si cela compte, beaucoup de code est écrit en Cython, il devrait donc prendre en compte la mémoire qui y est allouée. Je ne suis pas marié à une solution Python pure (elle n'a pas besoin d'être portable), donc tout ce qui fonctionne sous Linux convient.

46
carl

Découvrez resource.setrlimit () . Cela ne fonctionne que sur les systèmes Unix, mais il semble que ce soit ce que vous cherchez, car vous pouvez choisir une taille de segment de mémoire maximale pour votre processus et ses enfants avec le paramètre resource.RLIMIT_DATA.

EDIT: Ajouter un exemple:

import resource

rsrc = resource.RLIMIT_DATA
soft, hard = resource.getrlimit(rsrc)
print 'Soft limit starts as  :', soft

resource.setrlimit(rsrc, (1024, hard)) #limit to one kilobyte

soft, hard = resource.getrlimit(rsrc)
print 'Soft limit changed to :', soft

Je ne sais pas exactement quel est votre cas d'utilisation, mais il est possible que vous deviez limiter la taille de la pile à la place avec resouce.RLIMIT_STACK. Dépasser cette limite enverra un signal SIGSEGV à votre processus. Pour le gérer, vous devrez utiliser une pile de signaux différente, comme décrit dans la commande setrlimit Linux man page . Cependant, je ne suis pas sûr que sigaltstack soit implémenté en python. Cela pourrait donc s'avérer difficile si vous souhaitez récupérer après avoir dépassé cette limite.

47
xitrium

Regardez ulimit . Il permet de définir des quotas de ressources. Peut aussi avoir besoin de paramètres de noyau appropriés.

0
SpliFF

Le code suivant alloue de la mémoire à la taille spécifiée du groupe de résidents

import resource

def set_memory_limit(memory_kilobytes):
    # ru_maxrss: peak memory usage (bytes on OS X, kilobytes on Linux)
    usage_kilobytes = lambda: resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
    rlimit_increment = 1024 * 1024
    resource.setrlimit(resource.RLIMIT_DATA, (rlimit_increment, resource.RLIM_INFINITY))

    memory_hog = []

    while usage_kilobytes() < memory_kilobytes:
        try:
            for x in range(100):
                memory_hog.append('x' * 400)
        except MemoryError as err:
            rlimit = resource.getrlimit(resource.RLIMIT_DATA)[0] + rlimit_increment
            resource.setrlimit(resource.RLIMIT_DATA, (rlimit, resource.RLIM_INFINITY))

set_memory_limit(50 * 1024)  # 50 mb

Testé sur la machine Linux.

0
Ariunbayar