суббота, 7 июля 2012 г.

Продаю объектив Nikkor AF-S DX 18-105/3.5-5.6G ED VR (в Гомеле)

Объектив был куплен год назад вместе с фотоаппаратом в качестве штатника. За год использования никаких нареканий к нему не было, фронт- или бэк-фокуса не выявлено. Сейчас находится в отличном состоянии. Продаю в связи с тем, что уже почти полностью обеспечил себе этот диапазон фокусных расстояний более светосильными объективами.

Продаю в Гомеле за 200y.e.

К комплекте сам объектив, передняя и задние крышки, родной чехол для объектива. Купон европейской гарантии Nikon (хотя вряд ли он уже актуален):

Мое собственное мнение по поводу этого объектива – отличный бюджетный вариант среднефокусного зума в качестве штатника для недорогой зеркалки. Особенно для поездок на отдых, куда не хочется везти кофр со сменной оптикой или просто стремно брать с собой дорогую оптику. При хорошем освещении работает отлично, небольшая светосила в таких условиях вообще не будет ощущаться. Для слабой освещенности или же если хочется обеспечить совсем маленькую глубину резкости (диафрагмы от 2.8 или больше) это стекло не подойдет. Но для таких условий зумы будут стоить побольше раза в два-три-четыре-пять-…

Лично мне в этом объективе не хватало фокусного расстояния на длинном конце, поскольку люблю снимать тайком и брать объект крупно. Поэтому для меня адекватной заменой 18-105 мог бы стать 18-200/3.5-5.6, но сейчас он новый стоит $950-$1000 или б/у-ный в районе $800-$850. Что, на мой взгляд, слишком дорого для объектива с небольшой светосилой.

По сравнению с таким же бюджетным Nikon-овским 55-200/4-5.6 этот 18-105, хоть и проигрывает по максимальному фокусному расстоянию, зато быстрее фокусируется и минимальное расстояние фокусировки у него меньше, так что для съемки цветочков, например, 18-105 удобнее.

В общем, повторюсь, за свои деньги это отличный штатник для недорогой Nikon-овской зеркалки.

Ниже примеры фотографий, сделанных исключительно этим объективом (на Nikon D90). При отличном освещении:


Пенная вечерика, Турция.

Цветы, Турция.

Море, Турция.

Парк, Гомель.

При недостаточном освещении, невозможности использования вспышки и отсутствии штатива:


Выставка кошек, Гомель.

Дартс, Belarus Open 2011.

четверг, 5 июля 2012 г.

[prog.bugs] Не ходят сообщения? Отжирается память?

Через пару дней свалю в отпуск и заброшу блог на несколько недель. Напоследок расскажу поучительную, на мой взгляд, историю.

Некоторое время назад случилась не просто жопа, а просто охеренных рамеров жопа с большой буквы Ж. Утром телефонный звонок из нашей техподдержки (а это уже показатель чего-то из ряда вон). По словам дежурного наш комплекс работает как-то странно: в одну сторону сообщения ходят, в другую нет. Конкретной причины никто не знает, толком что происходит никто не знает, что делать не понятно и вообще полный ахтунг, особенно со стороны клиентов.

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

Первый лучик света проклюнулся когда дошла очередь до анализа консольных логов компонента – потоки stdout и stderr перехватываются и укладываются в отдельный файл. Размер этого файла был более 200Mb и постоянно увеличивался. Процентов 95% его содержимого составляли сообщения об ошибке о том, что не удалось сконвертировать текст из UCS-2 в UTF-8.

Нашли место программы, в котором эта ошибка фиксируется. Проанализировали конфигурацию компонента. Оказалось, что трафик одного из клиентов подвергается дополнительному анализу. И как раз сегодня этот клиент запустил новый поток данных, при обработке которых и диагностируется ошибка.

Выяснилось, что в этом фрагменте кода есть ошибка – префикс данных клиента выкусывается неправильно, после чего некорректный UCS-2 текст (в нем оказывалось нечетное количество байт) отдается внешней библиотеке на перекодировку. Та диагностирует проблему, мы эту диагностику посылаем в stderr. Отсюда и строки в консольном логе.

Сразу же вносятся правки, новая версия заливается на сервера, проблема исчезает, все работает шустро, память не течет. Возникает первая версия – внешняя библиотека при обработке некорректной UCS-2 последовательности портит память. Причем так, что мгновенного сбоя приложения не происходит, зато начинается утечка памяти.

Начинаются эксперименты по ее проверке. Но все они завершаются неудачно. Какие бы корявые строки не подсовывали внешней библиотеке, в каком бы количестве, в каком бы окружении… Нет ни растрела, ни утечки, все пучком.

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

Как ни стыдно в этом признаваться, но в течении трех или четырех дней даже намеков на какую-нибудь реальную версию не было. Первые наметки появились когда взгляд случайно зацепился за временные метки в сообщениях консольного лога. Они имели странное распределение – сначала с десяток записей в течении 3-5 миллисекунд, затем пауза в 200-300 миллисекунд, затем следующая пачка записей, вновь за 3-5 миллисекунд, потом опять пауза.

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

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

Почему так?

Оказалось потому, что программа-монитор, из-под которой запускается компонент, которая следит за его работой и, заодно перехватывает stdout/stderr, не может справиться с темпом записи в stderr порядка 100-150 строк в секунду. Она ловит десяток, записывает их в свой лог, берет паузу в несколько сотен миллисекунд, затем ловит еще десяток и т.д. А поскольку в нашем компоненте запись в stderr синхронная, то и наш компонент стал регулярно засыпать на несколько сотен миллисекунд.

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

Расход памяти так же объяснялся очень просто: поскольку тормозил только один агент, а в SObjectizer-4 нет средств для защиты агентов от перегрузки, то остальные агенты постоянно грузили его новыми сообщениями, которые копились в очереди тормознутого агента и именно они вызывали расход памяти.

Вот так мозаика и сложилась: клиент дал новый большой поток данных, сработало правило по его анализу, это правило спровоцировало древний баг в коде, что привело к диагностике о невозможности конвертации UCS-2, которая шла в stderr, который перехватывался программой, неспособной делать это достаточно быстро.

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

Что еще более интересно, так это то, что древний баг с неправильным вырезанием префикса из данных был даже покрыт unit-тестами, причем несколькими. Просто и unit-тесты я сам писал, поэтому и в них ошибся на ту самую –1 (как это обычно бывает у программистов с +1 и –1).

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

PS. По некоторым причинам названия упомянутых в тексте компонентов, библиотек и программ огласить не могу.

среда, 4 июля 2012 г.

[life] Huang Guofu: вот о ком нужно вспомнить, когда кажется, что цель недостижима

В четырехлетнем возрасте он потерял обе руки, в 12-ть лет начал учиться рисовать, с 18-ти лет был вынужден зарабатывать этим ремеслом себе на жизнь.

Найдено здесь.

PS. Кстати, хороший ответ на вопросы вроде “Почему ты увлекаешься программированием?” или “Зачем ты играешь в дартс?” Да просто затем, что мне это нравится и есть возможность этим заниматься.

вторник, 3 июля 2012 г.

[life.extreme.video] Без страховки на радиовышке

Как человек, страдающий боязнью высоты, с первого раза смог посмотреть ролик только до половины.

PS. Понимаю, что подобные трюки дают исполнителям невротебенный заряд адреналина и +100500 к расширению собственных горизонтов возможного... Но вот если бы они от успешнего выполения таких номеров еще и солидное материальное вознаграждение получали, тогда бы понял, зачем это все. А так, ИМХО, выигрыш в случае удачи не компенсирует риска растаться с жизнью в случае неудачи.

PPS. Еще интересно, операторы тоже были без страховки?