Upload
it-people
View
789
Download
4
Embed Size (px)
DESCRIPTION
Citation preview
Low-latency и soft-realtime на Python
Денис КолодинЗАО «ИК-Форум»
Что такое latency?
LATENCYвременная задержка между полезной работой
latency
Что такое real-time?
REAL-TIMEсистема с известной максимальной latency
(при этом задержкой можно пренебречь)
Классификация алгоритмов
CPU-BOUNDСкорость алгоритма зависит линейно от скорости процессора
IO-BOUNDСкорость алгоритма зависит линейно от
скорости ввода-вывода
Python и real-time
Ограничения:• Global Interpreter Lock• Невысокая скорость выполнения вычислений• Активное использование malloc• Сборщик мусора
Преимущества:• Простота проектирования• Лёгкое межпроцессное взаимодействие• Отсутствие JIT• Низкоуровневые интерфейсы
Как написать real-time код?•Асинхронность– (шаблон Reactor)
• Гранулярность•Управление памятью• Расчёт penalty
•Модули:– threading– multiprocessing– сtypes
•Использование cython
Не заставляйте ваших клиентов ждать!
Асинхронность
• Шаблон проектирования Reactor• Используйте волокна вместо потоков• Примеры реализации – Twisted, Tornado
Не занимайте ресурсы
напрасно
Асинхронность
from twisted.internet import reactorfrom twisted.internet import task
def routine_1(): print ("Routine 1")
def routine_2(): print ("Routine 2")
t1 = task.LoopingCall(routine_1)t1.start(0)
t2 = task.LoopingCall(routine_2)t2.start(0)
reactor.run( )
Работаетв 2 и 3 :)
Не создаётся конкурирующий контекст потока
Гранулярность
• Обработка данных отдельно от подсистемы взаимодействия
• Минимальная подготовка к ответу• Отложенные результаты (deferreds)
Минимизируйте время обмена
данными
Гранулярность
from threading import Thread, Lockfrom datetime import datetime
lock = Lock()counter = 0
def worker(tiny): global counter with lock: counter += 1 id = counter r = range(1000000)
if not tiny: yield [id, sum(r)] else: result = [id, None] yield result s = 0 for x in r: s += x if x % 100: yield result[1] = s
Освобождение ресурсов
Ресурсоёмкая работа не должна блокировать
программу
Управление памятью
• Выделение памяти создаёт непредсказуемую latency
• Создавайте объекты заранее (пул)• Используйте объекты повторно
(контейнеры)
Выделяйте память заранее
Управление памятью
class Stack(object):
def __init__(self, size): self.index = -1 self.storage = [None] * size
def put(self, value): try: self.index += 1 self.storage[self.index] = value except IndexError: self.index -= 1 raise
def pop(self): try: self.index -= 1 result = self.storage[self.index] self.storage[self.index] = None return result except IndexError: self.index += 1 raise
ЭффективностьO(1)
Отказ от выделения памяти сокращает время выполнения
Добавление с поиском
Расчёт penalty
• Ставьте паузы в потоках, когда нет задач• Увеличивайте паузу после каждого «отбоя»• Установите лимит ожидания
Предотвращайте пустую работу
Управление памятью
from threading import Threadfrom Queue import Queue, Emptyfrom time import sleep
class SmartThread(Thread):
def __init__(self, penalty=0): super(SmartThread, self).__init__() self.daemon = True self.penalty = penalty self.step = penalty / 10 self.sleep = 0 self.queue = Queue()
def run(self, penalty=False): while True: try: d = self.queue.get_nowait() self.wait except Empty: if self.penalty: if self.sleep < self.penalty: self.sleep += self.step sleep(self.sleep)Ожидание в момент простоя
Процессор не греется!
Модули
• threading (фоновая работа)• multiprocessing (вычислительная нагрузка)• ctypes (программные интерфейс ОС)
Используйте модули
Cython
• Язык для создания Python расширений• Высокая скорость работы кода• Миграция критичных компонент в C
Используйте cython
СПАСИБО ЗА ВНИМАНИЕ ;)