Завершить вызов функции, если это займет более 1 миллисекунды Python - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть список функций черного ящика (без обработки критических данных, без побочных эффектов от вызова, можно прекратить преждевременно), которые необходимо выполнить и их возвращаемые значения агрегированы:

aggregate = [result for fn in seq for result in fn()]

Функции обычно возвращаются в течение нескольких микросекунд, однако существуют крайние случаи, на которые я не могу повлиять, из-за которых некоторые из них иногда вызывают исключение, возвращают недопустимый тип (например, None вместо итерируемого) или зависают бесконечно.

Чтобы обработать недопустимые выходные данные и исключения, я написал декоратор:

def safe_call(fn, valid_type, default, error_handler=None):
    try:
        val = fn()
        if isinstance(val, valid_type):
            return val
        if error_handler is not None:
            error_handler(TypeError("Invalid return type"))
    except Exception as e:
        if error_handler is not None:
            error_handler(e)
    return default

Теперь единственной проблемой являются зависания.Полное приведенное выше выражение должно всегда вычисляться в течение миллисекунд, и чтобы убедиться, что я пытаюсь реализовать тайм-аут 1 мс для каждой функции в последовательности.

Я пробовал многопоточность и многопроцессорность, но яне может должным образом завершить проблемные потоки, и издержки запуска нового процесса слишком высоки и сами по себе превышают значение тайм-аута в 1 миллисекунду.

Я пытался использовать сигналы, эталонный тест, указывающий на 25% накладных расходов на каждый вызов, что является приемлемым, но оценка выполняется с точки зрения django, который не запускается в главном потоке, поэтому сигналы не работают должным образом.

Мой текущий обходной путь - иметь отдельный процесс для каждой функции, постоянно синхронизирующийся с ее функцией.родительский процесс через очередь, ожидающий вызова.Таким образом, родитель может инициировать вызов по требованию, подождать 1 мс, а затем проверить, был ли результат отправлен обратно - сохранить результат, если он есть, или завершить процесс в противном случае.

Он работает в том, что касается производительности, но из-за этого решения накладные расходы памяти составляют 1400-1700%, что недопустимо.

Так, как мне тайм-аут вызова функции с помощью <Точность 1 мс без огромных накладных расходов памяти? </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...