Редактор изображений с использованием технологии флеш как элемент веб-приложения: проблемы и решения
Аннотация
Рассмотрены некоторые возможные пути решения проблем, возникающих при построении веб-приложений, на примере конкретного элемента веб-приложения приложения, а именно, редактора изображений, разработанного с использованием технологии флеш. Из обсуждаемого материала делаются обобщения и предлагаются читателю в форме небольших и понятных советов, подкреплённых конкретными примерами использования. Статья может быть полезна программистам, создающим приложения для веб.
Ключевые слова: веб-приложение, сайт, оптимизация, технология флеш, редактор изображений № гос. регистрации 0420900096\000905.13.01 - Системный анализ, управление и обработка информации (по отраслям)
Факультет высоких технологий, ЮФУ
Небольшой группой разработчиков, в состав которой входил и автор данной статьи, успешно спроектирован и реализован веб-сайт blingeasy.com (http://blingeasy.com), предоставляющий неквалифицированным пользователям возможность просто и быстро применять различные графические эффекты к загруженным изображениям и добавлять на изображения различную анимацию.
Кроме обычных, общих для большинства веб-приложений задач по оптимизации быстродействия системы, в ходе работы над проектом так же возникла и не совсем обычная задача. Для обеспечения возможности пользователя редактировать изображение в веб-приложении используется редактор изображений, построенный с использованием технологии флеш. Этой задаче, её решению и некоторым общим выводам и советам и посвящена данная статья.
Первый вопрос, который возник — это вопрос отправки результатов работы пользователя на сервер. Наиболее простым способом отправить результаты являлось формирование серии изображений средствами технологии флеш и отправка этих изображений по сети на сервер. Такой подход позволял сделать серверную часть приложения максимально простой. Всё, что нужно делать серверной части — это конвертировать пришедшие изображения в формат гиф (gif), затем собрать их в единый рисунок и оптимизировать по размеру. Первое действие отлично выполнялось программой convert из пакета ImageMagick (http://imagemagick.org/, лицензия GPL). Второе и третье действия тоже очень просто и хорошо выполнялись с помощью программы gifsicle (www.lcdf.org/gifsicle/, лицензия GPL). Но, кроме очевидного преимущества данного подхода, связанного с простой реализации серверной части приложения, так же очевиден и его недостаток — необходимость пересылать серию изображений по сети. Кроме того, длительность самого формирования серии изображений флеш-редактором значительно зависела от мощности процессора на компьютере пользователя. Даже в локальной сети и с хорошим процессором на машине пользователя (то есть в идеальных условиях) этот процесс занимал до 1 минуты, а при переходе в глобальную сеть, время даже для не самых сложных изображений увеличивалось до 5 минут. Конечно же, такое время ожидания становилось абсолютно неприемлемым, особенно в условиях, когда конкурирующий продукт совершал ту же самую операцию в среднем за время меньше 20 секунд. Заказчик же ставил задачу свести ожидаемое время формирования изображения к 5 секундам.
При подробном рассмотрении стало ясно, что основными ресурсами, которые использовались при данной операции были процессор пользовательского компьютера и сеть. Если бы мы смогли отказаться от интенсивного использования сети и процессора, то это бы дало возможность значительно уменьшить время ожидания пользователя. С другой стороны, все необходимые изображения для формирования результата, а так же набор мощных процессоров (по сравнению со средним пользовательским) у нас есть на сервере и всё, чего нам не хватает для построения результирующего изображения на сервере — это описания действий, производимых пользователем в редакторе. Возникает вопрос — не быстрее ли будет переслать на сервер лишь данные о действиях пользователя, а уже на сервере формировать изображение? Этим путём мы решили пойти. Теперь основную работу делал прототип программы-построителя изображений, написанный на языке php (с использованием всё тех же imagemagick и gifsicle), а флеш-редактор отправлял на сервер только xml-файл с полным описанием действий пользователя. При таком подходе, конечно же, мы вынуждены были делать большое количество дополнительных действий для точного повторения пользовательского рисунка на сервере, но результат того стоил — время формирования запроса и передача его по медленной (глобальной) сети теперь занимали даже в очень сложных случаях не более двух секунд, а среднее время стало меньше одной секунды! Однако, не смотря на огромный выигрыш при создании и пересылке данных по сети, время генерации типичного результирующего изображения опять оказалось в пределах примерно 3-5 минут. То есть 5 минут занимало построение изображения на сервере из присланных данных. Здесь можно задаться вопросом о том, где же выигрыш, а может быть даже кто-то может сказать «выменяли шило на мыло». Категорически с этим не соглашусь. Ситуация стала качественно иной: в первом случае мы «зажаты» между сетью, проприетарной технологией флеш и мощностью процессора пользователя. Ни один из этих трёх факторов мы не в силах изменить. Сейчас же всё в наших руках: мы можем оптимизировать алгоритм построения изображения, оптимизировать алгоритмы, реализованные в используемых библиотеках (вот оно, проявление реального преимущества свободного программного обеспечения!), можем выдвинуть более серьёзные требования к аппаратному обеспечению (попробуйте-ка сказать пользователю, что для того, чтобы воспользоваться сайтом, ему нужно иметь суперсовременный компьютер! А для заказчика такое требование выглядит вполне естественно), и в крайнем случае, мы можем даже частично или полностью реализовать алгоритм построения изображения на языке ассемблера. Конечно, это займёт какое-то время, но тем не менее задача вполне решаема. Откровенно говоря, после переноса основных действий с клиентской стороны на серверную, у нашей команды появилась практически полная уверенность в том, что проект увенчается успехом.
Итак, первый совет состоит в том, что если вы по каким-то причинам не можете оптимизировать окружение вашей программы (напомню, у нас таких причины набралось целых три: мы не могли оптимизировать алгоритмы создания изображений, поскольку они были встроены во флеш, а эта технология не позволяет делать никаких изменений внутри себя так как является закрытой; мы не могли предъявлять требования к аппаратному обеспечению пользователя и мы не могли предъявлять требования к скорости подключения пользователя к сети), то постарайтесь в этом окружении сделать только самые необходимые действия, а основную работу перенести туда, где ваши возможности шире. Вполне вероятно, такая тактика приведёт вас к успеху.
Ещё один, менее общий совет — если нужно послать много данных и у вас есть (или вы можете составить, как в нашем случае) точный алгоритм для генерации этих данных, то возможно есть смысл послать лишь метаданные, достаточные для того, чтобы воссоздать необходимые вам данные при после приёма информации. Даже при современном уровне развития сетей посылка большого количества данных обычно занимает довольно много времени. Метаданные будут, возможно, в десятки, а то и сотни раз компактнее, что позволит значительно сократить время их пересылки по сети. В нашем случае типичный объём передаваемых данных даже после сжатия получался примерно 7-10 мегабайт. Метаданные же у нас редко доходили до 100 килобайт.
Вернёмся к нашему приложению. Несмотря на успех с уменьшением времени передачи, общая ситуация с точки зрения заказчика изменилась, мягка говоря, не слишком сильно. Между 5 секундами и 5 минутами всё ещё зияла пропасть в шеть десятков раз. Чтобы сберечь немного нервных клеток и заказчику и себе, мы постарались объяснить ему полученные результаты. После достижения некоторого уровня взаимопонимания, работа продолжилась.
Следующим шагом мы переписали программу на языке си++. Это относительно простое действие сократило время генерации изображения примерно до 40-60 секунд. Всё ещё много, но уже не так фатально. Хотя если откровенно — не только не фатальный, а прямо-таки отличный результат, ведь мы ещё даже не пытались оптимизировать сам алгоритм.
Откуда совет — используйте подходящий для задачи инструмент. Построитель изображений на php, конечно же, не планировалось использовать в эксплуатации. И php выбирался для написания прототипа из-за своих преимуществ — скорости разработки относительно простых приложений и наличия нужных библиотек, а так же не в последнюю очередь потому, что его хорошо знала вся команда, и это позволяло отдать задачу любому свободному программисту, а так же давало возможность легко читать код любому члену команды. Тем не менее, скорость выполнения объективно преимуществом php не является, тем более что мы постоянно вызывали из кода php сторонние приложения, что тоже негативно сказывалось на производительности. Простое переписывание алгоритма на более подходящем для задачи языке дало ускорение примерно в 5 раз.
Далее, после анализа алгоритма стало ясно, что больше всего процессорного времени занимает одна из функций библиотеки imagemagick, переводящая изображение в формат гиф. Первой в этой ситуации вполне естественно проявила себя идея оптимизации библиотечного алгоритма (ведь код-то открыт). Но к счастью, одному из членов команды пришла в голову мысль просто попробовать другую библиотеку — gd (http://www.boutell.com/gd/, лицензия GPL) для преобразования изображения в нужный формат. Мы не переделывали весь алгоритм, лишь немного модифицировали код чтобы использовать новую библиотеку. Результат превзошёл даже самые смелые ожидания — среднее время упало ниже 12 секунд!
Тут явно напрашивается вывод (он же совет) — попробуйте все доступные инструменты. Вполне возможно что другая реализация будет в определённой части значительно превосходить ту, что вы уже пробовали. Если существуют подходящие проприетарные библиотеки — попробуйте попросить демо-версию (если верить слухам, часто это не является слишком большой проблемой). Вполне возможно, что затраченное время (а в случае проприетарной библиотеки и деньги, разумеется) окупится с троицей.
Далее, по условию задачи приложение должно сохранять 4 копии изображения разных размеров. Так как сервер обладает несколькими процессорами, а изображение уже сформировано (осталось перевести кадры в гиф-формат, создать единое изображение, сохранить и оптимизировать), то здесь есть возможность запустить оставшуюся часть процесса параллельно (изображения разных размеров создаются в разных программных потоках). Это уменьшило время выполнения, как и ожидалось, примерно в 3-4 раза.
Совет здесь — не забывайте про старые добрые «обычные» средства оптимизации алгоритмов, которые хорошо описаны в соответствующей литературе.
Хотелось бы отметить ещё один момент. За время выполнения проекта мы встретились с двумя ошибками в программном обеспечении. Одна ошибка проявилась при изменении размеров изображения на шестидесятичетырёх разрядной системе при использовании библиотеки ImageMagick. Мы её довольно быстро локализовали и поправили, без особых приключений. Другая ошибка встретилась в технологии флеш. Почему-то в некоторых случаях при посылке файла фшел-проигрыватель не посылал на сервер «печеньки» (куки) с идентификатором сессии. Без этого идентификатора не возможно точно определить пользователя, пославшего файл. В данном конкретном случае проблема, к счастью, тоже решилась довольно быстро написанием отдельного контроллера для обработки именно этого запроса флеш-редактора и добавлением идентификатора сессии непосредственно в данные, посылаемые при запросе.
Тем не менее, хотелось бы дать совет — при прочих равных лучше пользоваться теми продуктами, которые предоставляют возможность изменять их код. У нас такой возможности в данном случае не было (технология флеш — стандарт «де-факто» для создания подобных приложений ввиду некоторых объективных причин), но хотелось бы отметить, что хотя ошибки и присутствуют в той или иной мере в любом продукте, всё же риск получить серьёзную головную боль при встрече с ошибкой приложения, запрещающего изменение исходного кода выше, чем при встрече с таковой в приложении, разрешающем изменение исходного кода. Связано это не в последнюю очередь с тем, что как указал Джоэл Спольски (http://russian.joelonsoftware.com/), когда падает программа, код которой открыт и доступен для изменений — она падает тебе на колени вместе с исходными кодами и отладчиком. И практически всегда есть возможность устранить проблему. А когда падает закрытая программа — она падает как чёрный ящик. Обычно максимум, что можно сделать в такой ситуации — это лишь понять, при каких условиях программа падает. Но устранить проблему обычно нельзя либо ввиду законодательных ограничений, либо, если случай не совсем тривиальный — ввиду технической сложности задачи. Кроме того, в случае если вы сами не справляетесь с проблемой, то нужно учитывать тот момент, что для открытого продукта круг компаний, от которых можно получить техническую поддержку для данного конкретно продукта, обычно шире, чем круг компаний, предоставляющих поддержку для проприетарного продукта. Это даёт основания полагать, что цена поддержки для свободного продукта в общем случае может быть ниже, ввиду большего количества конкурирующих компаний.
В заключении хотелось бы отметить следующее: вышеприведённые советы сформировались на основе нашего позитивного опыта и публикуются с надеждой на то, что они будут полезны читателю и не более того.