October 30, 2012

О сборке мусора, деструкторах и разных питонах


В этом посте я писал почему работа с файлами и другими объектами, требующими гарантированного закрытия должна должна производиться через with. Однако кроме минуса в виде добавления в код лишнего уровеня вложенности with еще и решает только часть проблемы - если код обработки файла не локален (нужно возвращать дескриптор в вызывающий код или хранить неопределенное время) with не может помочь. И собственно никто вообще не может помочь - суровая реальность состоит в том, что python не гарантирует вызов деструктора объекта. Т.е. если вы работаете на CPython, и не создаете циклических ссылок, то за крайне редкими исключениями деструктор будет вызываться вовремя. Но если вы используете ironpython/jython/pypy то ситуация становится совсем печальна.

October 28, 2012

Зачем в python with

Долгое время при работе с файлами из python я писал примерно следующий код:

Без подсветки синтаксиса
def some_func(fname):
    fd = open(fname)
    some_data_processing(fd.read())
    return result

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

Но что будет если в some_data_processing произойдет исключение?

September 23, 2012

Установка питона и пакетов

В этой статье я попытаюсь описать процесс создания готового python окружения и работу с пакетами на пользовательском уровне. Статья расcчитана на новичков (в основном для студентов, слушающих мои курсы).

March 20, 2012

perf : современный Linux профилировщик

Иногда возникает необходимость заглянуть внутрь программы, что-бы посмотреть почему она "так тормозит". Естественно начинается все с высокоуровневых средств htop/atop/nettop/iotop/sar. Но если они показывают, что производительность упирается в процессор, то необходимо знать какие функции требуют больше всего вычислительных мощностей. Это может помочь как переписать свою программу для провышения производительности, так и подобрать оптимальные настройки для чужой.

Собственно функция профилировщика - найти узкие места в программе и выдать нам как можно больше информации о том куда уходят процессорные такты. Можно выделить три основных модели профилирования:

Гарантированное профилирование (determine - не нашел как перевести это лучше). Целевая программа модифицируется (чаще всего перекомпилируется с определенными флагами - -pg для gcc). - в код внедряются вызовы библиотеки профилирования, собирающие информацию о выполняемой программе и передающие ее профилировщику. Наиболее часто замеряется время выполнения каждой функции и после тестового прогона программы можно увидеть вывод, подобный следующему:

 %   cumulative   self              self     total
time   seconds   seconds    calls  ms/call  ms/call  name
33.34      0.02     0.02     7208     0.00     0.00  open
16.67      0.03     0.01      244     0.04     0.12  offtime
16.67      0.04     0.01        8     1.25     1.25  memccpy
16.67      0.05     0.01        7     1.43     1.43  write

Очевидным минусом гарантированного профилирования является необходимость перекомпиляции программы, что неудобно, а иногда и невозможно (если это не ваша программа, например). Также гарантированное профилирование значительно влияет на скорость исполнения программы, делая получение коректного времени исполнения затруднительным. Типичный представитель - gprof,

February 21, 2012

Генерируем внешние API по-питоновски

В python есть негласное правило - никогда не повторяйся. Чаще всего если в программе приходиться писать почти одно и то-же два раза, значит вы что-то сделали не так. Я приведу пример, как можно автоматизировать генерацию внешних API таким образом, что достаточно будет в одном месте в удобной и универсальной форме описать поддерживаемые вызовы, а все внешнее API для этих вызовов сделает написаный один раз код.

Итак мы пишем серверный компонент программы, который должен контролироваться внешними утилитами. Типичные варианты управления:

  • CLI - административный интерфейс командной строки, так-же удобен для разработки
  • REST - для других языков, WebUI & Co
  • RCP в каком-то виде (thrift, PyRo, etc)

Нам нужна библиотека, которая позволит один раз задать интерфейсы API функций, сгенерирует по ним интерфейсы для всех внешних API, будет автоматически проверять входящие параметры и сделает удобочитаемую документацию. Для начала хватит.

February 11, 2012

Использование виртуальных машин для автоматического тестировани

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

При очевидных достоинствах (полная независимость тестов от внешнего мира, скорость исполнения, etc) у моков есть некоторое количество недостатков - самый главный это переход от тестирования того что должно быть сделано к тестирования того как это сделано. Если нужно проверить функцию, которая настраивает проброс порта, то вместо тестирования результата (правильного прохождения пакетов) проверяется, что iptables вызвалась с правильными параметрами.

February 10, 2012

Запуск процессов в linux с ограничением ресурсов


Иногда хочется ограничить максимальное количество ресурсов доступных процессу. Последней пинком стали юнит-тесты из текущего проекта - из-за ошибок они несколько раз съели все 8Gb ОЗУ и отправили систему в глубокий своп, откуда она со скрипом доставалась минут 15. Полная виртуализация таких случаях избыточна - нужно что-то по легче. В linux для этого есть cgroups (control groups) - они позволяют поместить процесс (вместе со всеми его потомками) в контейнер, имеющий доступ только к части ресурсов системы. На самом деле cgroups умеют больше, чем просто ограничение ресурсов - тут и счетчики производительности и другая статистика.

cgroups можно манипулировать вручную или с помощью libcgroup. Последний способ значительно удобнее и по нему есть отличная документация от redhat. Она обязательна к прочтению - есть несколько не очевидных моментов (для пользователей ubuntu - в этом дистрибутиве по умолчанию cgroups монтируются в /sys/fs/cgroups).

January 16, 2012

LXC - виртуализация без виртуализации

Таблица снизу это обзор текущих систем виртуализации с позиции того, насколько большую часть хост системы виртуальные машины используют напрямую:

                               Матрешка виртуализации

    ==========================================================================================
    Используется          Название              Примеры:
    совместно
    с хостом
    ==========================================================================================
    ничего                Эмуляция              QEMU, Boсsh
    ------------------------------------------------------------------------------------------
    CPU                   Виртуализация         KVM, VmWare, XEN, Hyper-V
    ------------------------------------------------------------------------------------------
    Аппаратура            Intel VT-d, SR-IOV    Может использоваться совместно 
                                                с системой виртуализации (kvm)
    ------------------------------------------------------------------------------------------
    Драйвера              Паравиртуализация     XEN, VirtIO, VMWare tools
    ------------------------------------------------------------------------------------------
    Ядро OS               Контейнеры            LXC, Solaris Zones, OpenVZ, Linux VServer
    ==========================================================================================

В первой графе - слои системы "компьютер + ОС" - чем ниже, тем более высокий уровень (что-то типа уровней ISO для сетевого стека ). Средняя графа - название модели виртуализации. Третья графа - типичные примеры. Чем ниже, тем больше компонентов гостевые системы используют от хост-системы напрямую, тем меньше нагрузка на гипервизор и тем выше скорость работы.

Я немного расскажу о контейнерах вообще и LXC (LinuX Containers) в частности. Контейнеры (или виртуализация уровня операционной системы)- это группы процессов, изолированные от остальной системы, возможно с наложенными ограничениями, и имеющие доступ только к некоторой части ресурсов. Процессы из контейнера "видят" и могут напрямую взаимодействовать только с процессами из того же контейнера, им доступна только часть аппаратуры, а корень файловой системы контейнера с помощью chroot сдвинут в глубь файловой системы хоста (например, в /var/lib/lxc/my_container_1). Виртуализация всех необходимых подсистем ядра (таблицы монтирования, PID, маршруты IP, etc) позволяет контейнеру выглядеть как "нормальная" виртуалка.

January 12, 2012

libvirt & Co. Облако "на коленке". Часть 3 - Дисковые образы

Следующий шаг - разобраться с дисковыми образами виртуальных машин. Основные вопросы - как хранить, где хранить и как модифицировать.


Как хранить

  • raw - самый простой формат, прямая копия данных с диска.
  • qcow2 - основной формат qemu. Обладает большим спектром возможностей
  • vdi - формат, используемый VirtualBox'ом
  • vmdk - VMware формат
  • cow, qcow - каменный век

Обсуждать raw смысла не имеет - просто диск байт по байту. qcow2 самый распространенный и функциональный формат виртуальных дисков для qemu/xen.

  • содержит только те кластеры, в которые были записаны данные. Т.е. можно создать образ диска размером в 10G, но реальный размер файла будет расти только при фактической записи на диск.