Почему тормозит Silverlight?
- modified:
- reading: 5 minutes
Такой вопрос “Почему тормозит Silverlight?” достаточно часто можно услышать, особенно если вы разрабатываете решения при помощи технологии Silverlight. Часто вы не можете выиграть тендер, или уговорить заказчика на использование технологии Silverlight в вашем приложении, только потому что за ним уже закрепилась эта популярность мышления, что все приложения на Silverlight тормозят. Давайте попробуем обсудить этот вопрос.
Пример с SQL.RU
Недавно я начал посматривать на сообщения в ветке WPF, Silverlight форума http://sql.ru, там дал рекомендацию об использовании Фреймворков MVVM (моя позиция известна), и напоролся на такой вот вопрос:
а не подскажите, чем занимается процессор по одной из ссылок с этого сайта, когда я его не трогаю? Предположения какие?
Отступление: Вообще, впечатления от форума sql.ru пока такие, что в любом треде начинается просто бестолковый флуд о том хорошо Silverlight или нет.
Так вот, по поводу того самого приложения http://surfity.com/#/Images. Действительно, если там набрать что-то в поиске, а затем нажать на кнопку Search то после самого поиска можно обнаружить такую картину:
В время простоя приложение продолжает использовать процессор почти на полную. Чем-то занимается в бэкграунде. Понятное дело, что все немного подтормаживает от такого упорства приложения. Я не могу дать ответ почему именно в этом случае такая проблема. Но один раз я решал подобный баг, созданный не мной, но который может допустить любой разработчик.
Пример нашей команды
Идея была простая. Был график, который рисовался при помощи Syncfusion контролов (мои любимые контролы, на этот раз ошибка была наша). Задача была отобразить линию (типа Target Line: красная линия, которая обозначала где “хорошо” превращается в “плохо”) на обычном Column графике. Примерно это выглядело так:
Контрол Chart, в этом случае, сам рассчитывает необходимую ему градацию для осей координат, и в зависимости от того, какие максимальные и минимальные значения присутствуют в коллекции значений, расставляет максимум и минимум на осях. На картинке это примерно от 70 до 80. Дальше разработчик, например, знает что Target Line это 78 – должен посмотреть есть ли на оси ординат такое значение, и если есть, нарисовать линию. Очевидно, что ему нужно какое-то событие от контрола Chart, вроде “График построился и готов”, чтобы он мог определить где рисовать линию, но такого события нет. Один из вариантов: подписаться на событие LayoutUpdated, который вызовется после того, как график нарисуется:
public partial class MainPage : UserControl
{ public MainPage()
{
InitializeComponent(); Chart.LayoutUpdated += new EventHandler(Chart_LayoutUpdated);
}
void Chart_LayoutUpdated(object sender, EventArgs e)
{ // Draw line...
}
}
А в методе Chart_LayoutUpdated уже добавить линию в контрол Chart. Вроде все просто. После реализации проверяем – все отлично работает. Отправляем исходный код в TFS. Видите проблему? Думаю, не многие сразу ее смогут заметить.
После долгих тестирований, человек, который принимает приложение, говорит: “Все хорошо, но приложение подтормаживает в целом, нельзя ли как-то сделать пошустрее этот ваш Silverlight?”. Понятное дело, что у вас готов стандартный ответ, вроде “Это бизнес приложение, а не записная книжка, понятное дело, что оно подтормаживает, потому что работает.” Но это не в моем случае, я обожаю решать perfomance задачи, еще со времен разработки на C++, когда делали приложение, которое рисовало чертежи, и когда приложение собранное под Debug вместо 40 секунд начинало рисовать чертежи за 10 (в Release за секунду), то я испытывал настоящий кайф. Потому я ответил, что попробую посмотреть что можно сделать. Первым делом открыл приложение и начал долго и упорно с ним работать, утечек памяти серьезных не видел, как ело от 150 до 200 Мб, так и продолжало держаться в этих рамках. Но заметил, что если ничего не делать, то приложение все равно на одном из экранов продолжает есть по 30-40% процессора, хотя на остальных по 5%. Хорошо, что у меня было приложение Silverlight Spy, при помощи которого я и начал анализировать наше приложение и увидел в Event Monitor, что на этом самом проблемном экране циклично и постоянно вызывается event LayoutUpdated. Тогда я и познакомился с этим кодом и с этой проблемой. Конечно, после того как график нарисовался и вызвалось событие LayoutUpdated, мы добавляем еще элемент в контрол, и разумеется вызывается опять тот же event LayoutUpdated и так по кругу.
Вот скажите, как часто вы тестируете свои приложения на то, что оно может работать долго? Как часто вы открываете даже простой Task Manager чтобы посмотреть как ведет себя ваше приложение?
Выводы
Очевидно, что отчасти тормознутой эту платформу сделали мы сами, разработчики. Команда разработки Silverlight тоже имеет множество косяков со своей стороны, можно посмотреть только сколько memory leak находили в самом ядре и базовых контролах Silverlight. Но все же, эти memory leak находят, и настоящие Silverlight разработчики подходят к этому очень щепетильно, и в итоге выпускают отличные решения.
Итак, почему же тормозят приложения на Silverlight? Потому что эта технология позволяет писать веб-приложения любым разработчикам от начинающих до гуру: дружелюбная среда разработки, уж очень простой язык разработки, огромное количество справочных материалов. Можно ли взять начинающего разработчика и попросить его сделать веб-приложение на Html+JavaScript или Flash, чтобы оно работало, было еще и интересным/привлекательным? Я говорю о приложениях для бизнеса, о сайтах-энциклопедий, а не об мелких игрушках и баннерах. Я даю на этот вопрос с уверенностью в 90% ответ “нет”.
Поэтому в будущем, если будете делать упор на разработку решений на Silverlight, учитывайте:
- нужно тратить время на изучение поведения приложения;
- в команде нужно иметь одного (число зависит от проекта, конечно же) специалиста, который мог бы решать серьезные проблемы с perfomance, и объяснять народу почему эти проблемы происходят;
- это managed environment, и потому, в пике работы, если с памятью быть не очень аккуратными, то можно загромождать огромные массивы памяти только для временной работы, которые будут освобождены не сразу;
И давайте создавать поменьше тормознутых приложений
P.S. Больше чем уверен, что появятся вопросы: “Покажите нормальное приложение на Silverlight”. Сразу отвечу, что не знаю таких. Наше приложение, в принципе, ведет себя хорошо, заказчики довольны, проблемы с perfomance по мере их возникновения решаем. Показать его не могу, потому что это intranet приложение.