Pull to refresh
129
0
Александр Карпинский @homm

Например: Программист

Send message

Разоблачение рекламной статьи Intel

Reading time4 min
Views48K
Некоторе время занимаясь реализацией различных алгоритмов обработки изображений, я не мог не узнать о пакете Intel Integrated Performance Primitives (Intel IPP). Это набор высокопроизводительных функций обработки одно-, двух- и трехмерных данных, использующих возможности современных процессоров на полную. Это такие кирпичики с универсальными интерфейсами, из которых можно строить свои приложения и библиотеки. Продукт этот, безусловно, коммерческий, поскольку входит в поставку других средств разработки и отдельно не распространяется.

С тех пор, как я узнал об этом пакете, меня не покидало желание узнать, насколько быстро в нем реализован ресайз изображений. Каких-то официальных бенчмарков или данных о производительности в документации нет, как нет и бенчмарков от сторонних разработчиков. Самое близкое, что мне удавалось найти — бенчмарки кодека JPEG от проекта libjpeg-turbo.

И вот, позавчера, в процессе подготовки статьи «Методы ресайза изображений» (прочтение которой очень желательно для понимания дальнейшего изложения) в очередной раз наткнулся на статью, о которой и пойдет речь:

libNthumb, The NHN* Performance Primitive for Real-Time Creation of Thumbnail Image with Intel IPP Library
Читать дальше →
Total votes 95: ↑89 and ↓6+83
Comments20

Ликбез: методы ресайза изображений

Reading time7 min
Views124K
Почему изображение, масштабированное с бикубической интерполяцией, выглядит не как в Фотошопе. Почему одна программа ресайзит быстро, а другая — нет, хотя результат одинаковый. Какой метод ресайза лучше для увеличения, а какой для уменьшения. Что делают фильтры и чем они отличаются.

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


Этот человек сидит среди ромашек, чтобы привлечь ваше внимание к статье.
Читать дальше →
Total votes 99: ↑93 and ↓6+87
Comments72

Вы не можете закачать файлы на сервер в мобильном Safari 8.0

Reading time3 min
Views20K
Печально, но факт. Новая версия iOS содержит баг, который делает невозможным отправку любых файлов на сервер из браузера. Когда вы выбираете файл в любой форме на HTML странице и пытатесь его отправить, браузер посылает запрос без файла. Он показывает, что ждет ответа на запрос, но на самом деле ответ не приходит.

Более того, баг касается не только HTML-форм. Если вы отправляете файл из Javascript, конструируя объект FormData (часть API XMLHttpRequest Level 2), это приводит к тому же результату. И даже если вы делаете то же самое из нативного приложения, которое является оберткой над HTML-браузером (например, Apache Cordova), то получаете такой же результат.

Почему же не приходит ответ. Если бы файл просто не отсылался, мы могли бы ожидать, что на сервер приходил бы пустой файл или сервер возвращал бы ошибку, что форма отправлена без файла. Однако сервер просто не шлет никакого ответа (даже 400 bad request) и не закрывает соединение. Все дело в том, какой именно запрос шлет Safari.
Читать дальше →
Total votes 41: ↑38 and ↓3+35
Comments19

Эффективная многопоточность в Python

Reading time7 min
Views76K
Хочу поделиться простым рецептом, как можно эффективно выполнять большое число http-запросов и других задач ввода-вывода из обычного Питона. Самое правильное, что можно было бы сделать — использовать асинхронные фреймворки вроде Торнадо или gevent. Но иногда этот вариант не подходит, потому что встроить event loop в уже существующий проект проблематично.

В моем случае уже существовало Django-приложение, из которого примерно раз в месяц нужно было выгрузить немного очень мелких файлов на AWS s3. Шло время, количество файлов стало приближаться к 50 тысячам, и выгружать их по очереди стало утомительным. Как известно, s3 не поддерживает множественное обновление за один PUT-запрос, а установленная опытным путем максимальная скорость запросов с сервера ec2 в том же датацентре не превышает 17 в секунду (что очень не мало, кстати). Таким образом, время обновления для 50 тысяч файлов стало приближаться к одному часу.

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

Получается, всего-то нужен пул потоков, который будет выполнять запросы. К счастью, такой пул уже написан. Начиная с версии 3.2 для унификации всей асинхронной работы в Питоне появилась библиотека concurrent.futures. Для второй версии Питона есть бекпорт под именем futures. Код до безобразия прост:

from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(concurrency) as executor:
    for _ in executor.map(upload, queryset):
        pass

Здесь concurrency — число рабочих потоков, upload — функция, выполняющую саму задачу, queryset — итератор объектов, которые по одному будут передаваться в задачу. Уже этот код при concurrency в 150 смог пропихнуть на сервера Амазона ≈450 запросов в секунду.
Читать дальше →
Total votes 31: ↑27 and ↓4+23
Comments12

Http запросы — мы все это делаем неправильно

Reading time3 min
Views188K
В проекте, над которым я работаю, мы используем огромное количество сторонних библиотек. Многие из них — адаптеры для различных сервисов. Что их объединяет, это то, что они работают с сетью. Json поверх http, soap поверх http, какие-то свои протоколы поверх http. Т.е. все так или иначе используют http. И как ни удивительно, мало кто из них пользуется преимуществами его последней версии. Я не поленился заглянуть в википедию, прошло ровно 14 лет как была принята спецификация http 1.1. И потому я решил обратиться с призывом:
image

Да, речь пойдет о keep alive. Суть в том, что, начиная с http 1.1, клиент и сервер могут договориться не закрывать установленное tcp-соединение после завершения запроса, а переиспользовать его для следующих запросов. Это нужно потому, что на установку соединения требуется время. Иногда это время больше, чем время самого запроса. И если все серверы уже давным-давно такую возможность поддерживают, а все браузеры и большинство других клиентов её используют, то у разработчиков различных библиотек для популярных языков программирования здесь почему-то пробел.
Читать дальше →
Total votes 167: ↑142 and ↓25+117
Comments169

Устранение утечек памяти в приложении на Питоне

Reading time7 min
Views37K
imageНедавно мне довелось разобраться и устранить несколько утечек памяти в популярном фреймворке Торнадо. Не беда, если вы никогда его не использовали, потому что описанное будет мало связано с ним. Рассказать я хочу о методах, которые я использовал для поиска и устранения утечек.

Все сказанное будет по большей части справедливо только для самой популярной реализации Питона — CPython. Как известно, в нем есть два механизма освобождения памяти. Первый из них — подсчет ссылок. Каждый раз, когда вы явно или не явно создаете новый объект, его счетчик ссылок равен единице. Если вы присваиваете этот объект новой переменной или передаете в качестве аргумента, его счетчик ссылок увеличивается. При выходе из функции количество ссылок на объекты, которые были в локальных переменных и аргументах, уменьшается. Если для какого-то объекта количество ссылок становится равным нулю, он немедленно уничтожается.

Это схема отлично работает до тех пор, пока не появляются объекты, ссылающиеся друг на друга. Самый простой пример — узлы какого-то дерева, хранящие ссылки на свои дочерние и родительский узлы. Узлы продолжат ссылаться друг на друга, даже когда не останется других внешних ссылок ни на один из них. Самое неприятное, что такие узлы могут ссылаться на какие-то другие данные и не давать их освободить. Чтобы устранить такие циклические ссылки, в Питоне существует второй механизм освобождения памяти — сборщик мусора. Он запускается время от времени, ставя выполнение остального кода на паузу, и анализирует все неосвобожденные объекты.

Формально, циклические ссылки нельзя назвать утечками: сборка мусора рано или поздно уничтожит такие объекты. Беда только в том, что Питон не может сам определить, когда еще рано, а когда уже поздно. В моем случае система просто прибивала процесс с Питоном, если сборка мусора не начиналась вовремя.
Читать дальше →
Total votes 98: ↑95 and ↓3+92
Comments8

Хостинг картинок за полчаса

Reading time5 min
Views40K
Сегодня проекты, особенно на начальном этапе, строятся из готовых блоков. Например, умный хостинг или сервис быстрой отправки сообщений в браузер пользователю. Складывая такие блоки по-разному, можно получить совершенно неожиданный результат. И чем больше разных блоков вам доступно, тем разнообразнее могут получаться проекты. Иногда появляются блоки, которыми можно заменить сразу несколько других блоков. И сами эти блоки — такие же проекты, состоящие из других блоков.

imageНасколько просто сейчас сделать такой сервис, как хостинг изображений? В принципе, его и раньше было несложно сделать. Но прогресс не стоит на месте, и за то же самое время теперь можно учесть больше нюансов. Я уже рассказывал о проекте Uploadcare. Это сервис, позволяющий облегчить работу с файлами: загрузку, хранение, обработку и раздачу конечному пользователю. Его и будем использовать в качестве основного блока.

Пример будет написан на Питоне. Во-первых, потому что Питон я знаю лучше всего, во-вторых библиотека pyuploadcare обновляется в первую очередь. На самом деле, для Uploadcare есть библиотеки под разные языки, и все они в open source. Если в нужном вам модуле отсутствует какая-то функциональность, можно дождаться, когда она появится, или дописать самому.
Читать дальше →
Total votes 60: ↑53 and ↓7+46
Comments18

Uploadcare — файловое хранилище для сайтов и приложений

Reading time3 min
Views14K
image
Привет! Хочу рассказать о проекте, который наверняка окажется полезным многим разработчикам. В двух словах объяснить, зачем он нужен, достаточно сложно, но я попробую. Uploadcare — сервис для приложений и сайтов, упрощающий получение файлов от пользователей, их хранение и передачу по сети.

Тот, кто хоть раз делал форму с <input type="file">, знает, что ничего сложного в этом нет, но есть неприятные моменты, возникающие по пути. Вот только некоторые из них:

— нельзя сохранить форму с файлом по ajax;
— нельзя показать форму с уже выбранным файлом;
— если вы ожидаете картинку, нужно убедиться, что загружена картинка;
— сервер должен быть готов принимать большое тело запроса;
— в некоторых фреймворках загруженный файл является источником повышенной опасности;
— удобная загрузка нескольких файлов реализуется достаточно сложно;
— индикация процесса загрузки реализуется еще сложнее;
— на диске сервера может закончиться место;
Читать дальше →
Total votes 56: ↑49 and ↓7+42
Comments44

История оптимизации alpha_composite в Pillow 2.0

Reading time7 min
Views5.9K
Недавно вышла вторая версия питоновской библиотеки для работы с изображениями Pillow. Как многие знают, это форк хорошо известной библиотеки PIL, которая, несмотря на свой солидный возраст, до недавнего времени оставалась самым вменяемым способом работы с изображениями в Питоне. Авторы Pillow наконец-то решили не только поддерживать старый код, но и добавлять новые возможности. И одной из этих возможностей стала функция alpha_composite().

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

С тех пор я уже смог написать для своих нужд более оптимальную реализацию, чем приведена в конце той статьи. И оказалось, что эта реализация быстрее alpha_composite() из новой версии Pillow, написанной на Си. Конечно, мне это польстило, но я все-таки решил попытаться улучшить реализацию из Pillow.
Читать дальше →
Total votes 23: ↑22 and ↓1+21
Comments11

Декоратор cached_property

Reading time3 min
Views26K
Как часто вы пишете такие конструкции?

class SomeClass(object):
    @property
    def param(self):
        if not hasattr(self, '_param'):
            self._param = computing()
        return self._param

    @param.setter
    def param(self, value):
        self._param = value

    @param.deleter
    def param(self):
        del self._param

Это очень удобно, значение атрибута param при таком подходе не хранится напрямую в объекте, но и не вычисляется каждый раз. Вычисление происходит при первом обращении, и это значение сохраняется в объекте под временным именем _param. Если меняются условия, от которых зависит значение param, его можно удалить, и тогда оно снова вычислится при следующем обращении. Или можно сразу присвоить актуальное значение, если таковое известно.

У этого кода есть и минусы: у объекта появляется лишний атрибут с именем _param; при каждом обращении к атрибуту вызывается метод param(), который делает проверку hasattr; получившийся код достаточно большой, особенно если таких атрибутов в классе несколько.
Читать дальше →
Total votes 49: ↑44 and ↓5+39
Comments3

Проблемы в библиотеке форм Django на примере поля ввода телефонов

Reading time5 min
Views9.8K
Как известно, в состав Django входит библиотека для генерации и обслуживания html-форм. Когда-то с Django в комплекте шла другая библиотека форм, но потом она была полностью переписана. Наверное, тогда разработчики решили много архитектурных проблем. Но и при работе с текущей библиотекой есть некоторые сложности. Именно об этом я и хочу поговорить.

Итак, задача. Пользователи очень любят оставлять на сайтах свои телефоны и другую приватную информацию. Причем, делать это они хотят, не задумываясь о том, как правильно её ввести: 8(908)1271669 или, скажем, 908 127 16 69. Посетители сайта очень любят видеть правильные телефоны, желательно единообразно оформленные: (+7 495) 722-16-25, +7 968 127-31-32. Получается, нужно валидировать и хранить номера в нормализованном виде, то есть без оформления. В поле, про которое я буду рассказывать, можно ввести больше одного номера телефона. Формат хранения определим как последовательности из 11 цифр, разделенные пробелом.
Читать дальше →
Total votes 28: ↑23 and ↓5+18
Comments22

Предлагаю помощь в подготовке иллюстраций

Reading time1 min
Views794
Наверное я кого-то просто достал с этой темой, а кого-то нереально достал.

Я опять хочу сказать про иллюстрации к статьям.

У меня сердце кровью обливается, когда по соседству со статьями, как правильно сжимать графику, какими утилитами пользоваться и какие есть особенности у каждого формата, люди лепят фотографии в png и скриншоты в jpeg.

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

Все просто — вы присылаете мне личное сообщение с ссылкой на опубликованную статью, или слепок черновика, сделанный с помошью сервиса peeep.us, если статья еще не опубликована. Я отвечаю вам ссылками на пережатые изображения. Иногда даю советы, что еще можно сделать.

Срок действия акции пока не ограничивается.

image — 17 кб. — 7,2 кб.
Total votes 212: ↑155 and ↓57+98
Comments77

Огромная очередь на открытии Microsoft Store

Reading time1 min
Views573
20 октября в Сиэтле открылся магазин University Village Microsoft Store. На открытии собралась огромная очередь.



Человеку с камерой так и не удалось найти людей, которые собираются что-нибудь купить в новом магазине. Очередь стояла за бесплатными билетами на концерт группы Black Keys, которые раздавала Microsoft на открытии магазина.
Total votes 121: ↑97 and ↓24+73
Comments100

8123 байта хватит каждому

Reading time2 min
Views11K
Сегодня во время перевода одного сайта с таблиц MyISAM на InnoDB, у последних выяснилась одна интересна особенность. Запрос на изменение движка для двух таблиц возвращал странную ошибку «Got error 139 from storage engine». После поиска информации на эту тему, было выяснено, что данная ошибка возникает тогда, когда какая-либо строка таблицы не вмещается в половину страницы памяти, с которыми работает MySQL. Страницы эти равны 16 Кб, а половина, стало быть, 8 Кб.

Само по себе ограничение довольно странное, но на первый взгляд кажется трудно достижимым, ведь как известно, MySQL хранят текстовые данные в хранилище, отдельном от табличных строк. Оказалось, что это верно только на половину. На самом деле InnoDB хранит в отдельном хранилище только «излишки», к коим он не относит первые 768 байтов каждого текстового поля. Т.е. любой текст будет отъедать от длины строки столько байт, сколько он содержит, но не больше 768. Несложно подсчитать, что максимальное число текстовых полей длиной от 768 байт, которое можно безопасно хранить в одной таблице — 10. И действительно, если запустить пример, все пройдет гладко. Но стоит увеличить количество полей хотя бы на одно, и мы получим ту же ошибку, что и в начале.
Читать дальше →
Total votes 82: ↑75 and ↓7+68
Comments27

Руководство: пишем интерпретатор с JIT на PyPy

Reading time12 min
Views12K
Все исходные коды и примеры из этой статьи доступны здесь.

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

— набор инструментов для написания интерпретаторов языков программирования;
— реализация Питона с применением этого набора инструментов.

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

Я взялся за это руководство для того, чтобы лучше понять как работает PyPy и что он из себя представляет. Предполагается, что вы очень мало знаете о PyPy, поэтому я начну с самого начала.

Читать дальше →
Total votes 78: ↑74 and ↓4+70
Comments6

SSD на графике горячая/сумасшедшая

Reading time3 min
Views21K
Являясь сторонником твердотельных дисков …
The State of Solid State Hard Drives (октябрь 2009, англ.)
Revisiting Solid State Hard Drives (октябрь 2010, англ.)
… я чувствую себя этически и морально обязанным посвятить вас в маленький грязный секрет, открытый мной за последние два года использования твердотельных дисков. Твердотельные диски дохнут. В огромных количествах. И не просто дохнут. Я говорю об ужасных поломках «боже мой, что случилось со всеми моими данными». И это нифига не клево.

Я купил три твердотельных диска Crucial на 128 гигабайт в октябре 2009 для себя и двух других работников Stack Overflow. По состоянию на предыдущий месяц два из них уже сдохли. На днях я беседовал с Джоэлом во врем записи подкаста, и он сказал, что твердотельный диск от Intel в его Thinkpad, купленный примерно в то же время, тоже сдох.
Читать дальше →
Total votes 115: ↑103 and ↓12+91
Comments283

Анимированные баннеры на Javascript — это просто*

Reading time7 min
Views20K
*) На самом деле все равно сложно, но зато проще, чем было раньше.

История началась с постановки задачи: нужно сделать анимированный баннер с примерно тридцатью объектами средствами HTML+javascript за один день. За день, конечно, баннер сделан не был, а был сделан за два усилиями трех человекодней. После выполнения задания осталась библиотека пакетной анимации, которую я назвал Scenario. О её доработанной версии я и хочу рассказать.

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

Запуск сценария из любого места предельно прост:

var newScenario = [...];
$.scenario(newScenario, {
    complete: function(time) {
        alert('Готово!');
    }
});

Осталось только разобраться, что писать вместо трех точек в примере :)
Читать дальше →
Total votes 163: ↑158 and ↓5+153
Comments65

Правила подготовки скриншотов для статей

Reading time2 min
Views4.6K

1. Включите сглаживание шрифтов


Вы за компьютером с 90-го года, ваша сетчатка деформировалась, и вы выключаете сглаживание шрифтов даже в Windows 7. Но ради бога, прежде чем сделать скриншот, включите сглаживание, .
Читать дальше →
Total votes 304: ↑189 and ↓115+74
Comments73

Information

Rating
4,996-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity