Подтвердить что ты не робот

Как ограничить размер кучи?

Я иногда пишу программы Python, которые очень трудно определить, сколько памяти он будет использовать перед выполнением. Поэтому я иногда вызываю программу Python, которая пытается выделить огромное количество оперативной памяти, из-за чего ядро ​​сильно меняет местами и ухудшает производительность других запущенных процессов.

Из-за этого я хочу ограничить, сколько памяти куча Python может расти. Когда предел достигнут, программа может просто сработать. Какой лучший способ сделать это?

Если это имеет значение, в Cython написано много кода, поэтому он должен учитывать память, выделенную там. Я не женат на чистом решении Python (его не нужно переносить), поэтому все, что работает в Linux, прекрасно.

4b9b3361

Ответ 1

Отметьте resource.setrlimit(). Он работает только в системах Unix, но похоже, что это может быть то, что вы ищете, так как вы можете выбрать максимальный размер кучи для вашего процесса и ваших дочерних процессов с параметром resource.RLIMIT_DATA.

EDIT: добавление примера:

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

Я не уверен, что ваш вариант использования в точности, но вам может потребоваться установить ограничение на размер стека вместо resouce.RLIMIT_STACK. Пройдя этот предел, вы отправите сигнал SIGSEGV вашему процессу, и для его обработки вам потребуется использовать альтернативный стек сигналов, как описано в файле setrlimit Linux manpage. Я не уверен, что sigaltstack реализован в python, так что это может оказаться трудным, если вы хотите оправиться от перехода по этой границе.

Ответ 2

Посмотрите ulimit. Он позволяет устанавливать квоты ресурсов. Возможно, нужны соответствующие настройки ядра.

Ответ 3

Следующий код выделяет память на указанный максимальный размер резидентного набора

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

Протестировано на машине linux.