Случайно увидел сегодня веб-камеру за 400 рублей, и не смог удержаться и купил. Но просто поставить её и все было не интересно и поэтому задачу я поставил так:

 - online трансляция
 - работа с видео ( снятие скриншотов, определение движения на участке, заливка на фтп видео и/или фотографий.

Все настраивалось на ubuntu 9.10

Воткнув камеру в usb-порт я посмотрел в dmesg:

[   74.604470] uvcvideo: Found UVC 1.00 device USB Web-CAM        (04fc:2001)
[   74.687602] input: USB Web-CAM        as /devices/pci0000:00/0000:00:10.0/usb2/2-2/2-2:1.0/input/input5
[   74.687710] usbcore: registered new interface driver uvcvideo
[   74.687718] USB Video Class driver (v0.1.0)
[   75.367518] usbcore: registered new interface driver snd-usb-audio


Камера определилась, ура! Я уж думал придется пересобирать ядро и танцевать с бубном.

Используемый софт:

zoneminder - Linux video camera security and surveillance solution
mjpg-streamer - MJPG-Streamer grabs images of an UVC-compatible webcam and serves them via HTTP
Настройка zoneminder требует чтения документации, предупреждаю :)
mjpg-streamer пришлось использовать из-за того, что zoneminder не поддерживает камеры, которые обслуживаются драйвером uvcvideo ( как я понял после нескольких попыток настроить zoneminder работать напрямую с веб-камерой ).


Итак:
 - добавляем в /etc/rc.local ( или в любое другое место, которое вам нравится ;) )
/usr/bin/mjpg_streamer -i "input_uvc.so -r 640x480 -f 30" -o "output_http.so -p 8080" -b
Запускаем ручками, открываем браузер и смотрим:
http://localhost:8080/?action=stream
 Если вам повезло, то вы увидите то, что видит ваша веб-камера. В принципе на этом можно остановиться и дальше не читать.
 
 - Если хочется большей функциональности, настраиваем zoneminder

http://localhost/zm/index.php
 Идем в options -> images
STREAM_METHOD -> mpeg
OPT_CAMBOZOLA -> on
 Качаем камбозолу:
http://www.zoneminder.com/downloads.html
 там в самом низу страницы есть ссылка на скачивание.
В своей системе я положил её в
/usr/share/zoneminder/
 Выходим из опций и настраиваем камеру:
Add new monitor
Source Type -> remote
Function -> monitor ( прочитайте в документации какие бывают функции )
Remote Protocol -> http
Remote Host Name -> 127.0.0.1
Remote Host Port -> 8080
Remote Host Path -> /?action=stream
Остальные параметры подберите по своему вкусу.
Вот и все, теперь можно следить за собой и своим домом.
Еще раз советую прочитать документацию, из неё вы узнаете,
как включать запись, если было замечено движение и т.д.


Ну а я пойду настраивать nginx вместо апача, и автозаливку
роликов куда-нибудь для большей сохранности.


7

Просмотреть комментарии

  1. Очень подробно!
    А что лучше использовать для трансляции из под winxp, win_vista, win7?

    ОтветитьУдалить
  2. Под винду не знаю.

    ОтветитьУдалить
  3. Не получается подключить к zoneminder в качестве удаленной камеры китайский внешний видеорегистратор EDR-204H на 4 видеокамеры компании CCDCAM Security systems (они же Shenzhen CCDCAM Technology Co.,Ltd, www.ccdcam.cn.

    )

    Используемый Протокол - H.264.

    Порты видеорегистратора:
    - command port 3357
    - data port 3358
    - talk port 3360
    - http port 80
    IP регистратора - 192.168.1.110

    Перепробовал такие варианты настроек в zoneminder:
    - remote host name: 192.168.1.110, admin:88888888@
    192.168.1.110

    - remote host port: 80, 3357, 3358, 3360
    - remote host path - пустой, т.к. других данных не нашел
    Zoneminder пишет "Unable to probe local cameras, status is '255'".


    К видеорегистратору идет софт Remote Surveillance DVR Client некоего прозводителя NetVideo, данных о котором в сети нет кроме ссылки http://remote-surveillance-dvr-client.software.informer.com/.
    После установки также запускается WEB-клиент с 192.168.1.110, но только в windows (т.е. вероятно это не клиент в самом видеорегистраторе).
    Софт работает, для входа спрашивает учетную запись (admin:88888888).

    Насколько я понимаю, доступ идет по http, а не по rtp (указал в настройках zoneminder).
    Также вместо формата jpeg указал mpeg в zoneminder.
    Пробовал настроить другой софт видеонаблюдения под windows xp - тоже не смог.

    От всех ответов на вопросы о настройках производитель таллантливо уходит.


    Краткое описание регистратора - http://www.diytrade.com/china/4/products/6959779/H_264_Stand-Alone_DVR.html

    Пожалуйста, подскажите:
    1. Что указать в remote host name, remote host port, remote host path?
    2. Как узнать remote host path?
    3. Есть ли утилита для перебора вариантов настроек IP-камеры

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

    ОтветитьУдалить
  4. Не получается подключить к zoneminder в качестве удаленной камеры китайский внешний видеорегистратор EDR-204H на 4 видеокамеры компании CCDCAM Security systems (они же Shenzhen CCDCAM Technology Co.,Ltd, www.ccdcam.cn.

    )

    Используемый Протокол - H.264.

    Порты видеорегистратора:
    - command port 3357
    - data port 3358
    - talk port 3360
    - http port 80
    IP регистратора - 192.168.1.110

    Перепробовал такие варианты настроек в zoneminder:
    - remote host name: 192.168.1.110, admin:88888888@
    192.168.1.110

    - remote host port: 80, 3357, 3358, 3360
    - remote host path - пустой, т.к. других данных не нашел
    Zoneminder пишет "Unable to probe local cameras, status is '255'".


    К видеорегистратору идет софт Remote Surveillance DVR Client некоего прозводителя NetVideo, данных о котором в сети нет кроме ссылки http://remote-surveillance-dvr-client.software.informer.com/.
    После установки также запускается WEB-клиент с 192.168.1.110, но только в windows (т.е. вероятно это не клиент в самом видеорегистраторе).
    Софт работает, для входа спрашивает учетную запись (admin:88888888).

    Насколько я понимаю, доступ идет по http, а не по rtp (указал в настройках zoneminder).
    Также вместо формата jpeg указал mpeg в zoneminder.
    Пробовал настроить другой софт видеонаблюдения под windows xp - тоже не смог.

    От всех ответов на вопросы о настройках производитель таллантливо уходит.


    Краткое описание регистратора - http://www.diytrade.com/china/4/products/6959779/H_264_Stand-Alone_DVR.html

    Пожалуйста, подскажите:
    1. Что указать в remote host name, remote host port, remote host path?
    2. Как узнать remote host path?
    3. Есть ли утилита для перебора вариантов настроек IP-камеры

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

    ОтветитьУдалить
  5. Вопрос
    все заинсталили но вот на фтп сервер заливает jpg возможно ли сделать так что бы лило прямым потоком в одном из форматов mpg,mpeg,avi

    ОтветитьУдалить
  6. @doph - как я знаю, протокол фтп не подразумевает "лить прямым потоком". Если бы у меня была такая задача, я бы как-нибудь подмонтировал файловую систему через самбу или нфс.
    Но если нет такой возможности, то, возможно, вам подойдет: http://curlftpfs.sourceforge.net/
    Сам не пробовал.

    ОтветитьУдалить
  7. прости наверное плохо сформулировал вопрос у меня ЗМ 1.24.2 писали что есть в нем возможность записи данных не в по кадровом jpg а уже прямым потоком с IPкамер в формате mpeg,avi,mpg но вот как это сделать найти не могу ,а Jpg ест место просто на глазах

    ОтветитьУдалить
  1. https://utcc.utoronto.ca/~cks/space/blog/linux/KernelMemoryZones

    # cat /proc/buddyinfo
    Node 0, zone      DMA      0      1      1      0      0      0      1      0      1      1      3
    Node 0, zone    DMA32  14461   9784   9378    136      6      2      0      0      0      0      0
    Node 0, zone   Normal 127027      0      0      2      3      2      3      1      0      1      0
    Node 1, zone   Normal 276309  55592   5505   1433    279      2      1      1      0      1      0 
     # getconf PAGESIZE
    4096

    Страниц в памяти DMA32 по 4kb 14461 штука. По 8kb - 9784, по 16kb - 9378 страниц и т.д.
    Если много чанков по 1 странице в 4kb - значит память сильно фрагментирована.

    https://utcc.utoronto.ca/~cks/space/blog/linux/DecodingPageAllocFailures

    0

    Добавить комментарий

  2. http://perl.plover.com/classes/ext2fs/
    http://www.nongnu.org/ext2-doc/ext2.html
    http://www.linuxforums.org/articles/journalling-block-device-jbd-_1544.html
    http://www.dfrws.org/2012/proceedings/DFRWS2012-13.pdf
    http://homepage.smc.edu/morgan_david/cs40/analyze-ext2.htm
    http://ols.fedoraproject.org/OLS/Reprints-2008/kumar-reprint.pdf
    0

    Добавить комментарий

  3. Понадобилось мне отправлять логи strace на другой хост для диагностики работы команды fsfreeze. Пришлось делать так:

    На сервере:
    nc -k -l 1234

    На клиенте:
    strace -f -s 20000 fsfreeze --freeze / |& nc proxy01h.dps.net 1234
    0

    Добавить комментарий

  4. 0

    Добавить комментарий

  5. apt-get -o Dpkg::Options::="--force-confnew" install your-package
    
    
    export DEBIAN_FRONTEND=noninteractive; apt-get install --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" your-package
    
    
    
    
    0

    Добавить комментарий

  6. remove-scsi 

    #! /bin/bash
    #----------------------------------------------------------------------
    # Description: a simple script to remove SCSI devices
    # Author: Artem S. Tashkinov 
    # Created at: Tue Sep 15 18:30:41 YEKST 2009
    # Computer: localhost.localdomain
    # System: Linux 2.6.31-k8l on i686
    #
    # Copyright (c) 2009 Artem S. Tashkinov  All rights reserved.
    # Copyright (c) 2011 Nikolay M. "Livid" Yakimov  All lefts reserved.
    #
    #----------------------------------------------------------------------
     
    strhb="hot-pluggable SCSI devices"
    DEVLIST=/sys/class/scsi_disk/*/device
     
    echo "We have found the following $strhb:"
     
    i=0
    for item in $DEVLIST; do
            i=$((i+1))
            d_id[$i]="$item"
            echo -n " $i: "
            cat "$item"/model | tr -d '\n'
            echo -n " "
            ls "$item"/block | tr '\n' ' '
            echo
    done
     
    echo -n "Please, enter a device number to remove or 0 to exit: "
    read devn
     
    if ! [ "$devn" -eq "$devn" 2> /dev/null ]; then
            echo "Error: $devn isn't a number, bye."
            exit 2
    fi
     
    if [ "$devn" -lt 1 -o "$devn" -gt $i -o "$devn" -eq 0 ]; then
            echo "No action taken, bye."
            exit
    fi
     
    echo 1 > "${d_id[$devn]}"/delete
    echo "Done. Consult with dmesg to find out if the device was actually removed" 
     
     
    rescan-scsi 

    #! /bin/bash
     
    SCSI=/sys/class/scsi_host
    test ! -d "$SCSI" && echo "Error: cannot find $SCSI directory." && exit 1
    cd "$SCSI" || exit 1
     
    for i in *; do
            echo -n "Scanning $i ..."
            echo "- - -" > $i/scan && echo " done."
    done
     
    echo "Finished. Consult with 'dmesg' for details."
    
    0

    Добавить комментарий

  7. Предположим у нас есть две таблицы:







    Нам надо найти все пиццерии где подают и cheese и supreme.
    В терминах реляционной алгебры запрос, который нам нужен будет выглядеть так:

    R÷S
    Так получилось, что в курсе  Introduction to Databases, а точнее в викторине по реляционной алгебре не допускается использовать данный оператор. Поэтому деление пришлось реализовывать теми операторами, которые были разрешены.
    Итак, первым делом выбираем список пиццерий:

    \project_{pizzeria} R;

    Потом перемножаем его со списком всех доступных пицц:

    \project_{pizzeria} R /cross S;

    Получаем следующую табличку:







    Далее, вычитаем из получившейся таблицы таблицу R:

    ( \project_{pizzeria} R /cross S ) /diff R;

    Получаем одну строчку:
    Dominos - cheese.

    Ну а далее все просто и я просто опишу это окончательным выражением:

    \project_{pizzeria} R \diff ( \project_{pizzeria} ( ( \project_{pizzeria} R /cross S ) /diff R ));

    Разобраться с задачей мне помог следующий документ: https://www.dropbox.com/s/ns0a46ihweeb1fz/divisionEnglish.pdf

    0

    Добавить комментарий

  8. fahd.blog: Finding the Maximum using Relational Algebra

    fahd.blog: Finding the Maximum using Relational Algebra


    \project_{value}(T)
    \diff
    \project_{value} (
        \select_{value < value2}(
          \project_{value}(T)
          \cross
          \rename_{value2}(\project_{value}(T))
        )
    )
    
    where:
    • \cross is the relational cross-product operator
    • \diff is the relational diff operator
    • \project_{attr_list} is the relational projection operator
    • \rename_{new_attr_name_list} is the relational renaming operator
    • \select_{cond} is the relational selection operator
    0

    Добавить комментарий

  9. http://habrahabr.ru/post/154235/

    Очень частой проблемой, является попытка понять «насколько быстрый сервер?» Среди всех тестов наиболее жалко выглядят попытки оценить производительность дисковой подсистемы. Вот ужасы, которые я видел в своей жизни:
    • научная публикация, в которой скорость кластерной FS оценивали с помощью dd (и включенным файловым кешем, то есть без опции direct)
    • использование bonnie++
    • использование iozone
    • использование пачки cp с измерениема времени выполнения
    • использование iometer с dynamo на 64-битных системах


    Это всё совершенно ошибочные методы. Дальше я разберу более тонкие ошибки измерения, но в отношении этих тестов могу сказать только одно — выкиньте и не используйте. 


    bonnie++ и iozone меряют скорость файловой системы. Которая зависит от кеша, задумчивости ядра, удачности расположения FS на диске и т.д. Косвенно можно сказать, что если в iozone получились хорошие результаты, то это либо хороший кеш, либо дурацкий набор параметров, либо действительно быстрый диск (угадайте, какой из вариантов достался вам). bonnie++ вообще сфокусирована на операциях открытия/закрытия файлов. т.е. производительность диска она особо не тестирует.

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

    С опцией же direct (iflag=direct для чтения, oflag=direct для записи) dd проверяет лишь линейную скорость. Которая совершенно не равна ни максимальной скорости (если мы про рейд на много дисков, то рейд в несколько потоков может отдавать большую скорость, чем в один), ни реальной производительности.

    IOmeter — лучше всего перечисленного, но у него есть проблемы при работе в linux. 64-битная версия неправильно рассчитывает тип нагрузки и показывает заниженные результаты (для тех, кто не верит — запустите его на ramdisk).

    Спойлер: правильная утилита для linux — fio. Но она требует очень вдумчивого составления теста и ещё более вдумчивого анализа результатов. Всё, что ниже — как раз подготовка теории и практические замечания по работе с fio.

    Постановка задачи


    (текущая VS максимальная производительность)
    Сейчас будет ещё больше скучных букв. Если кого-то интересует количество попугаев на его любимой SSD'шке, ноутбучном винте и т.д. — см рецепты в конце статьи. 

    Все современные носители, кроме ramdisk'ов, крайне негативно относятся к случайным операциям записи. Для HDD нет разницы запись или чтение, важно, что головки гонять по диску. Для SSD же случайная операция чтения ерунда, а вот запись малым блоком приводит к copy-on-write. Минимальный размер записи — 1-2 Мб, пишут 4кб. Нужно прочитать 2Мб, заменить в них 4кб и записать обратно. В результате в SSD'шку уходит, например, 400 запросов в секундну на запись 4кб которые превращаются в чтение 800 Мб/с (!!!!) и записи их обратно. (Для ramdisk'а такая проблема могла бы быть тоже, но интрига в том, что размер «минимального блока» для DDR составляет около 128 байт, а блоки в тестах обычно 4кб, так что гранулярность DDR в тестах дисковой производительности оперативной памяти не важна).

    Этот пост не про специфику разных носителей, так что возвращаемся к общей проблеме. 

    Мы не можем мерять запись в Мб/с. Важным является сколько перемещений головки было, и сколько случайных блоков мы потревожили на SSD. Т.е. счёт идёт на количество IO operation, а величина IO/s называется IOPS. Таким образом, когда мы меряем случайную нагрузку, мы говорим про IOPS (иногда wIOPS, rIOPS, на запись и чтение соотв.). В крупных системах используют величину kIOPS, (внимание, всегда и везде, никаких 1024) 1kIOPS = 1000 IOPS. 

    И вот тут многие попадают в ловушку первого рода. Они хотят знать, «сколько IOPS'ов» выдаёт диск. Или полка дисков. Или 200 серверных шкафов, набитые дисками под самые крышки. 

    Тут важно различать число выполненных операций (зафиксировано, что с 12:00:15 до 12:00:16 было выполнено 245790 дисковых операций — т.е. нагрузка составила 245kIOPS) и то, сколько система может выполнить операций максимум.

    Число выполненых операций всегда известно и легко измерить. Но когда мы говорим про дисковую операцию, мы говорим про неё в будущем времени. «сколько операций может выполнить система?» — «каких операций?». Разные операции дают разную нагрузку на СХД. Например, если кто-то пишет случайными блоками по 1Мб, то он получит много меньше iops, чем если он будет читать последовательно блоками по 4кб.

    И если в случае пришедшей нагрузки мы говорим о том, сколько было обслужено запросов «какие пришли, такие и обслужили», то в случае планирования, мы хотим знать, какие именно iops'ы будут.

    Драма состоит в том, что никто не знает, какие именно запросы придут. Маленькие? Большие? Подряд? В разнобой? Будут они прочитаны из кеша или придётся идти на самое медленное место и выковыривать байтики с разных половинок диска? 

    Я не буду нагнетать драму дальше, скажу, что существует простой ответ:
    • Тест диска (СХД/массива) на best case (попадание в кеш, последовательные операции)
    • Тест диска на worst case. Чаще всего такие тесты планируются с знанием устройства диска. «У него кеш 64Мб? А если я сделаю размер области тестирования в 2Гб?». Жёсткий диск быстрее читает с внешней стороны диска? А если я размещу тестовую область на внутренней (ближшей к шпинделю) области, да так, чтобы проходимый головками путь был поболе? У него есть read ahead предсказание? А если я буду читать в обратном порядке? И т.д.


    В результате мы получаем цифры, каждая из которых неправильная. Например: 15kIOPS и 150 IOPS. 

    Какая будет реальная производительность системы? Это определяется только тем, как близко будет нагрузка к хорошему и плохому концу. (Т.е. банальное «жизнь покажет»). 

    Чаще всего фокусируются на следующих показателях:
    1. Что best case всё-таки best. Потому что можно дооптимизироваться до такого, что best case от worst будет отличаться едва-едва. Это плохо (ну или у нас такой офигенный worst).
    2. На worst. Имея его мы можем сказать, что СХД будет работать быстрее, чем полученный показатель. Т.е. если мы получили 3000 IOPS, то мы можем смело использовать систему/диск в нагрузке «до 2000».


    Ну и про размер блока. Традиционно тест идёт с размером блока в 4к. Почему? Потому что это стандартный размер блока, которым оперируют ОС при сохранении файла. Это размер страницы памяти и вообще, Очень Круглое Компьютерное Число.

    Нужно понимать, что если система обрабатывает 100 IOPS с 4к блоком (worst), то она будет обрабатывать меньше при 8к блоке (не менее 50 IOPS, вероятнее всего, в районе 70-80). Ну и на 1Мб блоке мы увидим совсем другие цифры. 

    Всё? Нет, это было только вступление. Всё, что написано выше, более-менее общеизвестно. Нетривиальные вещи начинаются ниже.

    Для начала мы рассмотрим понятие «зависимых IOPS'ов». Представим себе, что у нас приложение работает так:
    • прочитать запись
    • поменять запись
    • записать запись обратно


    Для удобства будем полагать, что время обработки нулевое. Если каждый запрос на чтение и запись будет обслуживаться 1мс, сколько записей в секунду сможет обработать приложение? Правильно, 500. А если мы запустим рядом вторую копию приложения? На любой приличной системе мы получим 1000. Если мы получим значительно меньше 1000, значит мы достигли предела производительности системы. Если нет — значит, что производительность приложения с зависимыми IOPS'ами ограничивается не производительностью СХД, а двумя параметрами: latency и уровнем зависимости IOPS'ов.

    Начнём с latency. Latency — время выполнения запроса, задержка перед ответом. Обычно используют величину, «средняя задержка». Более продвинутые используют медиану среди всех операций за некоторый интервал (чаще всего за 1с). Latency очень сложная для измерения величина. Связано это с тем, что на любой СХД часть запросов выполняется быстро, часть медленно, а часть может попасть в крайне неприятную ситуацию и обслуживаться в десятки раз дольше остальных.

    Интригу усиливает наличие очереди запросов, в рамках которой может осуществляться переупорядочивание запросов и параллельное их исполнение. У обычного SATA'шного диска глубина очереди (NCQ) — 31, у мощных систем хранения данных может достигать нескольких тысяч. (заметим, что реальная длина очереди (число ожидающих выполнения запросов) — это параметр скорее негативный, если в очереди много запросов, то они дольше ждут, т.е. тормозят. Любой человек, стоявший в час пик в супермаркете согласится, что чем длиннее очередь, тем фиговее обслуживание.

    Latency напрямую влияет на производительность последовательного приложения, пример которого приведён выше. Выше latency — ниже производительность. При 5мс максимальное число запросов — 200 шт/с, при 20мс — 50. При этом если у нас 100 запросов будут обработаны за 1мс, а 9 запросов — за 100мс, то за секунду мы получим всего 109 IOPS, при медиане в 1мс и avg (среднем) в 10мс.

    Отсюда довольно трудный для понимания вывод: тип нагрузки на производительность влияет не только тем, «последовательный» он или «случайный», но и тем, как устроены приложения, использующие диск.

    Пример: запуск приложения (типовая десктопная задача) практически на 100% последовательный. Прочитали приложение, прочитали список нужных библиотек, по-очереди прочитали каждую библиотеку… Именно потому на десктопах так пламенно любят SSD — у них микроскопическая задержка (микросекундная) на чтение — разумеется, любимый фотошоп или блендер запускается в десятые доли секунды.

    А вот, например, работа нагруженного веб-сервера практически параллельная — каждый следующий клиент обслуживается независимо от соседнего, т.е. latency влияет только на время обслуживания каждого клиента, но не на «максимальное число клиентов». А, признаемся, что 1мс, что 10мс — для веб-сервера всё равно. (Зато не «всё равно», сколько таких параллельно запросов по 10мс можно отправить).

    Трешинг. Я думаю, с этим явлением пользователи десктопов знакомы даже больше, чем сисадмины. Жуткий хруст жёсткого диска, невыразимые тормоза, «ничего не работает и всё тормозит». 

    По мере того, как мы начинаем забивать очередь диска (или хранилища, повторю, в контексте статьи между ними нет никакой разницы), у нас начинает резко вырастать latency. Диск работает на пределе возможностей, но входящих обращений больше, чем скорость их обслуживания. Latency начинает стремительно расти, достигая ужасающих цифр в единицы секунд (и это при том, что приложению, например, для завершения работы нужно сделать 100 операций, которые при latency в 5 мс означали полусекундную задержку...). Это состояние называется trashing. 

    Вы будете удивлены, но любой диск или хранилище способны показывать БОЛЬШЕ IOPS'ов в состоянии trashing, чем в нормальной загрузке. Причина проста: если в нормальном режиме очередь чаще всего пустая и кассир скучает, ожидая клиентов, то в условии трешинга идёт постоянное обслуживание. (Кстати, вот вам и объяснение, почему в супермаркетах любят устраивать очереди — в этом случае производительность кассиров максимальная). Правда, это сильно не нравится клиентам. И в хороших супермаркетах хранилищах такого режима стараются избегать. Если дальше начинать поднимать глубину очереди, то производительность начнёт падать из-за того, что переполняется очередь и запросы стоят в очереди чтобы встать в очередь (да-да, и порядковый номер шариковой ручкой на на руке).

    И тут нас ждёт следующая частая (и очень трудно опровергаемая) ошибка тех, кто меряет производительность диска.

    Контроль latency во время теста


    Они говорят «у меня диск выдаёт 180 IOPS, так что если взять 10 дисков, то это будет аж 1800 IOPS». (Именно так думают плохие супермаркеты, сажая меньше кассиров, чем нужно). При этом latency оказывается запредельной — и «так жить нельзя».

    Реальный тест производительности требует контроля latency, то есть подбора таких параметров тестирования, чтобы latency оставалась ниже оговоренного лимита.

    И вот тут вот мы сталкиваемся со второй проблемой: а какого лимита? Ответить на этот вопрос теория не может — этот показатель является показателем качества обслуживания. Другими словами, каждый выбирает для себя сам.

    Лично я для себя провожу тесты так, чтобы latency оставалась не более 10мс. Этот показатель я для себя считаю потолком производительности хранилища. (при этом в уме я для себя считаю, что предельный показатель, после которого начинают ощущаться лаги — это 20мс, но помните, про пример выше с 900 по 1мс и 10 по 100мс, у которого avg стала 10мс? Вот для этого я и резервирую себе +10мс на случайные всплески).

    Параллелизм


    Выше мы уже рассмотрели вопрос с зависимыми и независимыми IOPS'ами. Производительность зависимых Iops'ов точно контролируется latency, и этот вопрос мы уже обсудили. А вот производительность в независимых iops'ах (т.е. при параллельной нагрузке), от чего она зависит?

    Ответ — от фантазии того, кто изобретал диск или конструировал хранилище. Мы можем рассуждать о числе головок, шпинделей и параллельных очередей записи в SSD, но всё это спекуляции. С точки зрения практического использования нас интересует один вопрос: СКОЛЬКО? Сколько мы можем запустить параллельных потоков нагрузки? (Не забываем про latency, т.к. если мы разрешим отправить latency в небеса, то число параллельных потоков отправится туда же, правда, не с такой скоростью). Итак, вопрос: сколько параллельных потоков мы можем выполнять при latency ниже заданного порога? Именно на этот вопрос должны отвечать тесты.

    SAN и NAS


    Отдельно нужно говорить про ситуацию, когда хранилище подключено к хосту через сеть с использованием TCP. О TCP нужно писать, писать, писать и ещё раз писать. Достаточно сказать, что в линуксе существует 12 разных алгоритмов контроля заторов в сети (congestion), которые предназначены для разных ситуаций. И есть около 20 параметров ядра, каждый из которых может радикальным образом повлиять на попугаи на выходе (пардон, результаты теста).

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

    bus saturation


    Последний вопрос — это вопрос затенения шины. О чём речь? Если у нас ssd способна выдать 400 МБ/с, а мы её подключаем по SATA/300, то очевидно, что мы не увидим всю производительность. Причём с точки зрения latency проблема начнёт проявляться задолго до приближения к 300МБ/с, ведь каждому запросу (и ответу на него) придётся ждать своей очереди, чтобы проскочить через бутылочное горлышко SATA-кабеля.

    Но бывают ситуации более забавные. Например, если у вас есть полка дисков, подключенных по SAS/300x4 (т.е. 4 линии SAS по 300МБ каждая). Вроде бы много. А если в полке 24 диска? 24*100=2400 МБ/с, а у нас есть всего 1200 (300х4). 

    Более того, тесты на некоторых (серверных!) материнских платах показали, что встроенные SATA-контроллеры часто бывают подключены через PCIx4, что не даёт максимально возможной скорости всех 6 SATA-разъёмов.

    Повторю, главной проблемой в bus saturation является не выедание «под потолок» полосы, а увеличение latency по мере загрузки шины.

    Трюки производителей


    Ну и перед практическими советами, скажу про известные трюки, которые можно встретить в индустриальных хранилищах. Во-первых, если вы будете читать пустой диск, вы будете читать его из «ниоткуда». Системы достаточно умны, чтобы кормить вас нулями из тех областей диска, куда вы никогда не писали.

    Во-вторых, во многих системах первая запись хуже последующих из-за всяких механизмов снапшотов, thin provision'а, дедупликации, компрессии, late allocation, sparse placement и т.д. Другими словами, тестировать следует после первичной записи. 

    В третьих — кеш. Если мы тестируем worst case, то нам нужно знать, как будет вести себя система когда кеш не помогает. Для этого нужно брать такой размер теста, чтобы мы гарантированно читали/писали «мимо кеша», то есть выбивались за объёмы кеша. 

    Кеш на запись — особая история. Он может копить все запросы на запись (последовательные и случайные) и писать их в комфортном режиме. Единственным методом worst case является «трешинг кеша», то есть посыл запросов на запись в таком объёме и так долго, чтобы write cache перестал стправляться и был вынужден писать данные не в комфортном режиме (объединяя смежные области), а скидывать случайные данные, осуществляя random writing. Добиться этого можно только с помощью многократного превышения области теста над размером кеша.

    Вердикт — минимум x10 кеш (откровенно, число взято с потолка, механизма точного расчёта у меня нет).

    Локальный кеш ОС


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

    Описание теста


    Итого:
    1) Мы тестируем worst case — 100% размера диска, который в несколько раз больше предположительного размера кеша на хранилище. Для десктопа это всего лишь «весь диск», для индустриальных хранилищ — LUN или диск виртуальной машины размером от 1Тб и больше. (Хехе, если вы думаете, что 64Гб RAM-кеша это много...).
    2) Мы ведём тест блоком в 4кб размером.
    3) Мы подбираем такую глубину параллельности операций, чтобы latency оставалось в разумных пределах.

    На выходе нас интересуют параметры: число IOPS, latency, глубина очереди. Если тест запускался на нескольких хостах, то показатели суммируются (iops и глубина очереди), а для latency берётся либо avg, либо max от показателей по всем хостам.

    fio


    Тут мы переходим к практической части. Есть утилита fio которая позволяет добиться нужного нам результата.

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

    fio выполняет операции над указанным файлом/файлами. Вместо файла может быть указано устройство, т.е. мы можем исключить файловую систему из рассмотрения. Существует несколько режимов тестирования. Нас интересует randwrite, randread и randrw. К сожалению, randrw даёт нам зависимые iops'ы (чтение идёт после записи), так что для получения полностью независимого теста нам придётся делать две параллельные задачи — одна на чтение, вторая на запись (randread, randwrite). 

    И нам придётся сказать fio делать «preallocation». (см выше про трюки производителей). Дальше мы фиксируем размер блока (4к).

    Ещё один параметр — метод доступа к диску. Наиболее быстрым является libaio, именно его мы и будем использовать.

    Практические рецепты


    Установка fio: apt-get install fio (debian/ubntu). Если что, в squeze ещё её нет.
    Утилита весьма хитро запрятана, так что «home page» у неё просто нет, только гит-репозиторий. Вот одно из зеркал: freecode.com/projects/fio

    При тесте диска запускать её надо от root'а.

    тесты на чтение


    Запуск: fio read.ini
    Содержимое read.ini
    [readtest]
    blocksize=4k
    filename=/dev/sda
    rw=randread
    direct=1
    buffered=0
    ioengine=libaio
    iodepth=32
    

    Задача подобрать такой iodepth, чтобы avg.latency была меньше 10мс.

    Тесты на запись


    (внимание! Ошибётесь буквой диска — останетесь без данных)
    [writetest]
    blocksize=4k
    filename=/dev/sdz
    rw=randwrite
    direct=1
    buffered=0
    ioengine=libaio
    iodepth=32
    

    Гибридные тесты


    самая вкусная часть:
    (внимание! Ошибётесь буквой диска — останетесь без данных)
    [readtest]
    blocksize=4k
    filename=/dev/sdz
    rw=randread
    direct=1
    buffered=0
    ioengine=libaio
    iodepth=32
    [writetest]
    blocksize=4k
    filename=/dev/sdz
    rw=randwrite
    direct=1
    buffered=0
    ioengine=libaio
    iodepth=32
    


    Анализ вывода


    Во время теста мы видим что-то вроде такого:
    Jobs: 2 (f=2): [rw] [2.8% done] [13312K/11001K /s] [3250/2686 iops] [eta 05m:12s]
    


    В квадратных скобках — цифры IOPS'ов. Но радоваться рано — ведь нас интересует latency.

    На выходе (по Ctrl-C, либо по окончании) мы получим примерно вот такое:

    ^C
    fio: terminating on signal 2
    read: (groupid=0, jobs=1): err= 0: pid=11048
      read : io=126480KB, bw=14107KB/s, iops=3526, runt=  8966msec
        slat (usec): min=3, max=432, avg= 6.19, stdev= 6.72
        clat (usec): min=387, max=208677, avg=9063.18, stdev=22736.45
        bw (KB/s) : min=10416, max=18176, per=98.74%, avg=13928.29, stdev=2414.65
      cpu          : usr=1.56%, sys=3.17%, ctx=15636, majf=0, minf=57
      IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=99.9%, >=64=0.0%
         submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
         complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
         issued r/w: total=31620/0, short=0/0
         lat (usec): 500=0.07%, 750=0.99%, 1000=2.76%
         lat (msec): 2=16.55%, 4=35.21%, 10=35.47%, 20=3.68%, 50=0.76%
         lat (msec): 100=0.08%, 250=4.43%
    write: (groupid=0, jobs=1): err= 0: pid=11050
      write: io=95280KB, bw=10630KB/s, iops=2657, runt=  8963msec
        slat (usec): min=3, max=907, avg= 7.60, stdev=11.68
        clat (usec): min=589, max=162693, avg=12028.23, stdev=25166.31
        bw (KB/s) : min= 6666, max=14304, per=100.47%, avg=10679.50, stdev=2141.46
      cpu          : usr=0.49%, sys=3.57%, ctx=12075, majf=0, minf=25
      IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=99.9%, >=64=0.0%
         submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
         complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
         issued r/w: total=0/23820, short=0/0
         lat (usec): 750=0.03%, 1000=0.37%
         lat (msec): 2=9.04%, 4=24.53%, 10=49.72%, 20=9.56%, 50=0.82%
         lat (msec): 100=0.07%, 250=5.87%
    


    Нас из этого интересует (в минимальном случае) следующее:
    read: iops=3526 clat=9063.18 (usec), то есть 9мс.
    write: iops=2657 clat=12028.23

    Не путайте slat и clat. slat — это время отправки запроса (т.е. производительность дискового стека линукса), а clat — это complete latency, то есть та latency, о которой мы говорили. Легко видеть, что чтение явно производительнее записи, да и глубину я указал чрезмерную. 

    В том же самом примере я снижаю iodepth до 16/16 и получаю:

    read 6548 iops, 2432.79usec = 2.4ms
    write 5301 iops, 3005.13usec = 3ms

    Очевидно, что глубина в 64 (32+32) оказалась перебором, да таким, что итоговая производительность даже упала. Глубина 32 куда более подходящий вариант для теста.

    Ориентировки по производительности


    Разумеется, все уже расчехляют пи… попугаемерки. Привожу значения, которые я наблюдал:
    • RAMDISK (rbd) — ~200kIOPS/0.1мс (iodepth=2)
    • SSD (intel 320ой серии) — 40k IOPS на чтение (0.8мс); около 800 IOPS на запись (после длительного времени тестирования)
    • SAS диск (15к RPM) — 180 IOPS, 9мс
    • SATA диск (7.2, WD RE) — 100 IOPS, 12мс
    • SATA WD Raptor — 140 IOPS, 12mc
    • SATA WD Green — 40 IOPS, и мне не удалось добиться latency <20 даже с iodepth=1

    Предупреждение: Если вы это будете запускать на виртуальных машинах, то
    а) если за IOPS'ы берут деньги — это будут весьма ощутимые деньги.
    б) Если у хостера плохое хранилище, которое надеется только на кеш в несколько десятков гигабайт, то тест с большим диском (>1Тб) приведёт к… проблемам у хостера и ваших соседей по хостингу. Некоторые хостеры могут обидеться и попросить вас вон.
    с) Не забывайте обнулять диск перед тестом (т.е. dd if=/dev/zero of=/dev/sdz bs=2M oflag=direct)
    0

    Добавить комментарий

  10. Думал написать статью, а оказывается в инете уже их полно. Так что просто оставлю список софта, через который можно это реализовать: NoCat HotSpotPA PacketFence ChilliSpot WiFiDog
    0

    Добавить комментарий

Ярлыки
Архив блога
Обо мне
Обо мне
Загрузка...