HighLoad.org – блог о высоких нагрузках
HighLoad.org > Делая Facebook в два раза быстрее

Делая Facebook в два раза быстрее
2010-03-03 08:53 my_fess  
Все знают, что чем быстрее интернет, тем он лучше. В Facebook мы стараемся сделать наш сайт как можно более дружелюбным; мы провели эксперименты, которые показали, что пользователи просматривают больше страниц и получают больше пользы от нашего сайта, когда он работает быстрее. Google и Microsoft заявили о схожих выводах относительно их задач на 2009 O’Reilly Velocity Conference. Итак, как же сделать Facebook быстрее? Во-первых, мы должны придумать способ измерять наш прогресс. Мы хотим оптимизировать для пользователей скорость просмотра страниц, так что нам нужно смотреть на три главных компоненты, влияющих на выполнение загрузки страницы: сетевое время, время генерации и время рендеринга.

Значения компонент

Сетевое время показывает, как долго пользователь ждет, пока данные передаются между его компьютером и Facebook. Мы не можем полностью контролировать сетевое время, так как у одних пользователей более медленное соединение чем у других, но мы можем уменьшить число байтов, необходимых для загрузки страницы; меньшее количество байтов означает меньшее сетевое время. 5 главных составляющих сетевого времени — байты cookies, HTML, CSS, JavaScript и изображения. Время генерации показывает, сколько проходит между получением запроса от пользователя нашим веб-сервером и отправкой ответа. Эта метрика измеряет эффективность нашего кода, а также нашего веб-сервера, кэширования, базы данных и сетевого оборудования. Уменьшение времени генерации полностью в наших руках и достижимо с помощью более чистого, быстрого кода и постоянного улучшения нашей внутренней архитектуры. Время рендеринга отображает, сколько нужно браузеру пользователя, чтобы обработать ответ от Facebook и отобразить полученную веб-страницу. Как и в случае с сетевым временем, мы некоторым образом ограничены здесь производительностью и поведением разных браузеров, но большей частью оно зависит от нас. Чем меньше данных мы отправляем пользователю, тем быстрее браузер сможет отобразить результат. Таким образом, минимизируя байты HTML, CSS, JavaScript и изображений мы также улучшим время рендеринга. Другой очевидный способ уменьшить время рендеринга — выполнять как можно меньше JavaScript до показа страницы пользователю. Три метрики, которые я описал эффективны для отображения отдельных компонент производительности, но мы ведь хотели объединить их в одно число, которое будет для нас главным показателем быстроты сайта. Мы назовем эту метрику TTI (Time-to-Interact, время взаимодействия), и будем считать ее лучшим способом понять, сколько приходится ждать пользователю пока значимое содержание страницы станет видимым и готовым для использования. На нашей домашней странице, например, TTI означает время, через которое становится видимой новостная лента.

Первые шаги

С начала 2008 до середины 2009, мы провели много времени, используя лучшие способы, разработанные пионерами веб-производительности, чтобы измерить и улучшить TTI. Для всех, кто всерьез хочет сделать свой веб-сайт быстрее, подборки Стива Соудера просто обязательны: Высокопроизводительные веб-сайты и Еще более быстрые веб-сайты. Мы также самостоятельно разработали несколько впечатляющих способов измерения и улучшения производительности Facebook, которые были описаны на 2009 O’Reilly Velocity Conference двумя инженерами Facebook, Дэвидом Вэем и Чангхао Джиангом. К июню 2009 мы сделали несколько значительных улучшений, сократив среднее время вполовину для пользователей Соединенных Штатов. Это был большой прогресс, но в то же время, Facebook стал очень популярным по всему миру и нам нужно было подумать об остальных пользователях. Мы решили измерить TTI для 75-го процентиля всех пользователей, чтобы получить более точные данные, какова скорость нашего сайта. Посмотрев на данные, мы поставили амбициозную цель — сократить это время в два раза к 2010 году; у нас было около 6 месяцев, чтобы сделать Facebook вдвое быстрее.

Шесть месяцев. Время пошло

При более близком рассмотрении, наши метрики подсказали нам, что основная проблема со скоростью страниц — в сетевом времени и времени рендеринга. Наше время генерации было (и остается) полем для серьезных улучшений, но такого прорыва оно не обеспечит. Итак, большая часть наших инженерных усилий была направлена на две цели: радикально уменьшить число байтов cookies, HTML, CSS и JavaScript, требуемых страницей Facebook, а также разработать новые фреймворки и методологии, которые позволят браузеру отображать содержимое страницы пользователю так быстро, насколько это возможно. Сокращение cookies потребовало нескольких инженерных трюков, но было довольно прямолинейным; за 6 месяцев мы уменьшили среднее число байтов cookie за запрос на 42% (до gzip). Чтобы уменьшить HTML и CSS, наши инженеры разработали новую библиотеку повторно используемых компонентов (построенной на основе XHP), из которых построены блоки всех наших страниц. До разработки этой библиотеки компонент, для каждой страницы было много своего HTML и CSS, хотя многие из этих страниц имели одинаковые возможности и функциональность. С библиотекой компонент, становится просто оптимизировать наш HTML в одном месте и увидеть результат по всему сайту. Другое преимущество состоит в том, что так как компоненты совместно используют правила CSS, как только пользователь скачал какие-то CSS, очень вероятно, что эти правила будут повторно использованы на следующей странице, вместо того ,чтобы скачивать полностью новый набор. Благодаря этим попыткам, мы сократили среднее число байтов CSS на страницу на 19% (после gzip) и байтов HTML на страницу — на 44% (до gzip). Эти резкие сокращения означают, что мы можем отправлять контент нашим пользователям быстрее, и браузеры могут обрабатывать его быстрее. Сокращение JavaScript было еще одним вызовом для нас. Facebook представляет собой динамичный и привлекательный сайт во многом благодаря функциональности JavaScript, которую мы создали. Но по мере того, как мы добавляли новые и новые возможности, мы писали все больше JavaScript, который приходилось скачивать пользователям, чтобы пользоваться сайтом. Вспомним, что скачивание и выполнение JavaScript — это одна из главных проблем, с которыми нам надо было бороться, чтобы улучшить сетевое время и время рендеринга. Чтобы разобраться с этой проблемой, наши инженерам пришлось по-новому взглянуть на то, где и зачем мы используем JavaScript. Мы заметили, что относительно небольшой набор функций может быть использован для построения большей части наших возможностей, которые можно сделать также-но-по-другому. Эта общая функциональность могла содержаться в очень маленькой, эффективной библиотеке, которая также кэшировалась бы на компьютере пользователя. Мы решили переписать наши основные модули на основе этой новой библиотеки, получившей название Primer, и увидели огромное 40%-е уменьшение (после gzip) в среднем количестве байт JavaScript на страницу. Поскольку Primer быстро скачивается, а потом кэшируется для будущих просмотров страниц, это также значит, что возможности, основанные исключительно на Primer доступны для использования сразу же после появления на экране; не нужно больше ждать, когда скачается JavaScript. Примером такой возможности является наш интерфейс обратной свзи, который позволяет пользователям комментировать, оценивать и делиться контентом, и который применяется везде в Facebook. Еще одна задача, о которой я хотел бы рассказать, нуждается в небольшом предисловии. Как было описано раньше, традиционная модель загрузки веб-страницы включает в себя отправку запроса пользователем на сервер, генерирование ответа сервером, отправку его назад браузеру, и конвертирование браузером этого ответа во что-то, что пользователь может видеть и с чем взаимодействовать. Если вы присмотритесь к этой модели, то увидете громадную проблему. Скажем, пусть серверу нужно несколько сотен миллисекунд, чтобы полностью подготовить и отправить ответ обратно пользователю. В то время, как сервер пыхтит, выполняя свою работу, браузер просто простаивает без дела, и ждет чего-нибудь, чем можно заняться. Что если мы сможем поставить всю эту процедуру на конвейер? Было бы замечательно, если сервер мог бы делать маленькую часть работы, скажем, за десять или пятьдесят миллисекунд, и дальше отправлять этот частичный ответ браузеру, который тогда мог бы начать скачивать JavaScript и CSS или даже начать отображать какое-нибудь содержимое. Как только сервер заканчивает следующую часть работы, он опять может послать результат браузеру. И так мы сможем повторять эту процедуру, пока сервер не сделает все, что от него требовалось. Таким образом, мы совместили значительную часть времени генерации с временем отображения, что уменьшило итоговое TTI, которое видит пользователь. В течение последних нескольких месяцев мы как раз внедрили эту возможность для страниц Facebook. Мы называем всю систему BigPipe (большая труба), и она позволяет нам разбивать наши веб-страницы на логические блоки контента, называемые Pagelets, и совмещать генерацию и рендеринг этих Pagelets. Например, глядя на домашнюю страницу, думайте о новостной ленте как об одном Pagelet, о блоке предложений — как другом, и о рекламном блоке как третьем. BigPipe не только сокращает TTI наших страниц, но также заставляет их казаться еще быстрее для пользователей, потому увидеть часть контента чуть раньше кажется более быстрым, чем увидеть все, но чуть позже.

Успех!

Я рад сказать, что 22 декабря, в результате этих и других усилий, мы объявили нашу цель ускорить сайт в два раза выполненной. У нас даже осталось целых 9 дней на отдых.

Автор статьи: Jason Sobel Дата: 19 февраля 2010 Оригинал статьи


комментарии [0]  | комментировать

  © 2010-2018 HIGHLOAD