Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="ru">
- <head>
- <meta charset="utf-8">
- <title>Yandex.Blog</title>
- <link rel="stylesheet" href="index.css">
- </head>
- <body>
- <main>
- <article class="content">
- <h4 class="pre_header">Блог компании Яндекс.</h4>
- <h1 class="header"><span class="red_symbol">Я</span>НДЕКС.ПОЧТА:
- КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ</h1>
- <p>
- Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то,
- какой он красивый, ни то, какой он удобный. Никому не понравится,
- когда все тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность,
- иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код
- и новая логика. Всё это напрямую влияет на скорость работы интерфейса.
- </p>
- <section>
- <h2>Что мы измеряем</h2>
- <p>Этапы первой загрузки:</p>
- <ol>
- <li>подготовка</li>
- <li>загрузка статики (HTTP-запрос и парсинг)</li>
- <li>исполнение модулей</li>
- <li>инициализация базовых объектов</li>
- <li>отрисовка</li>
- </ol>
- <p>Этапы отрисовки любой страницы:</p>
- <ol>
- <li>подготовка к запросу на сервер</li>
- <li>запрос данных с сервера</li>
- <li>шаблонизация</li>
- <li>обновление DOM</li>
- </ol>
- <p>
- — <q>Ок, теперь у нас есть метрики, мы можем отправить их на сервер</q> - говорим мы<br>
- — <q>Что же дальше?</q> - вопрошаете вы<br>
- — <q>А давай построим график!</q> - отвечаем мы<br>
- — <q>А что будем считать?</q> - уточняете вы<br>
- </p>
- <p>
- Как вы знаете, медиана – это серединное, а не среднее значение в выборке. Если у нас
- имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5. В общем случае
- медиана отлично показывает, сколько грузится средний пользователь.
- </p>
- <p>
- В случае ускорения или замедления медиана, конечно, изменится. Но она не может
- рассказать, сколько пользователей ускорилось, а сколько замедлилось.
- </p>
- <p>
- <abbr title="Application Performance Index">APDEX</abbr> – метрика,
- которая сразу говорит: хорошо или плохо. Метрика работает
- очень просто. Мы выбираем временной интервал [0; t], такой, что если время показа
- страницы попало в него, то пользователь счастлив. Берем еще один интервал, (t; 4t]
- (в четыре раза больше первого), и считаем, что если страница показана за это время,
- то пользователь в целом удовлетворен скоростью работы, но уже не настолько счастлив.
- И применяем формулу:
- <br>
- <em>(кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех)</em>
- <br>
- Получается значение от нуля до единицы, которое, видимо, лучше всего показывает,
- хорошо или плохо работает почта.
- </p>
- </section>
- <section>
- <h2>Как мы измеряем</h2>
- <p>
- Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять
- причину замедления: медленнее стал отвечать сервер либо слишком долго выполняется
- JavaScript. Выглядит это примерно так:
- <code>
- this.timings['look-ma-im-start'] = Date.now();<br>
- this.timings['look-ma-finish'] = Date.now();
- </code>
- </p>
- <p>
- C помощью <code>Date.now()</code> мы получаем текущее время. Все тайминги
- собираются и при отправке рассчитываются. На этапах разница между <var>end</var>
- и <var>start</var> не считается, а все вычисления производятся в конце:
- <code>
- var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];
- </code>
- </p>
- <p>
- И на сервер прилетают подобные записи:
- <code>serverResponse=50&domUpdate=60</code>
- </p>
- </section>
- <section>
- <h2>Как мы ускоряем</h2>
- <p>Чтобы снизить время загрузки почты при выходе новых версий, мы уже делаем следующее:</p>
- <ul>
- <li>включаем gzip</li>
- <li>выставляем заголовки кэширования</li>
- <li>фризим CSS, JS, шаблоны и картинки</li>
- <li>используем CDN</li>
- </ul>
- <p>
- Мы подумали: <q>А что если хранить где-то старую версию файлов, а при выходе новой
- передавать только diff между ней и той, которая сохранена у пользователя?</q>
- В браузере же останется просто наложить патч на клиенте.
- </p>
- <p>
- На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например,
- RFC 3229 «Delta encoding in HTTP» и «Google SDHC»,
- — но по разным причинам они не
- получили должного распространения в браузерах и на серверах.
- </p>
- <p>
- Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления,
- начали искать реализации diff на JS. На популярных хостингах кода нашли библиотеки:
- </p>
- <ul>
- <li>VCDiff</li>
- <li>google-diff-patch-match</li>
- </ul>
- <p>Для окончательного выбора библиотеки нам нужно сравнить:</p>
- <table>
- <thead>
- <tr>
- <th>Библиотека </th>
- <th>IE 9</th>
- <th>Opera 12</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>vcdiff</td>
- <td>8</td>
- <td>5</td>
- </tr>
- <tr>
- <td>google diff</td>
- <td>1363</td>
- <td>76 </td>
- </tr>
- </tbody>
- </table>
- <p>
- После того как мы определились с библиотекой для диффа, нужно определиться с тем,
- где и как хранить статику на клиенте.
- </p>
- <p>Формат файла с патчами для проекта выглядит так:</p>
- <pre><code>
- [
- {
- "k": "jane.css",
- "p": [patch],
- "s": 4554
- },
- {
- "k": "jane.css",
- "p": [patch],
- "s": 4554
- }
- ]
- </code></pre>
- <p>
- То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У каждого
- объекта есть три свойства. <var>k</var> — названия ключа в <var>localStorage</var>
- для этого ресурса. <var>p</var> — патч для ресурса, который сгенерировал vcdiff.
- <var>s</var> — чексумма для ресурса актуальной версии, чтобы потом можно было проверить
- правильность наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера.
- </p>
- <p>
- Алгоритм Бройдена — Флетчера — Гольдфарба — Шанно (BFGS) — итерационный метод численной
- оптимизации, предназначенный для нахождения локального максимума/минимума нелинейного
- функционала без ограничений.
- </p>
- <div class="algorithm">
- <pre>дано ε, x<sub>0</sub>
- инициализировать H<sub>0</sub>
- k = 0
- while ||∇f<sub>k</sub>|| > ε
- найти направление p<sub>k</sub> = -C<sub>k</sub>∇f<sub>k</sub>
- вычислить x<sub>k+1</sub> = x<sub>k</sub> + α<sub>k</sub>p<sub>k</sub>,
- α<sub>k</sub> удовлетворяет условиям Вольфе
- обозначить s<sub>k</sub> = x<sub>k+1</sub> - x<sub>k</sub> и
- y<sub>k</sub> = ∇f<sub>k+1</sub> - ∇f<sub>k</sub>
- вычислить C<sub>k+1</sub>
- k = k + 1
- end</pre>
- </div>
- <p>Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:</p>
- <ul>
- <li>
- CRC16/32 - алгоритм нахождения контрольной суммы,
- предназначенный для проверки целостности данных
- </li>
- <li>
- md5 - 128-битный алгоритм хеширования.
- Предназначен для создания«отпечатков» или дайджестов сообщения произвольной
- длины и последующей проверки их подлинности.
- </li>
- </ul>
- <p>Потому что он быстрый, компактный и легок в реализации.</p>
- </section>
- <section>
- <h2>Итог</h2>
- <p>Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:</p>
- <table>
- <thead>
- <tr>
- <th>Релиз</th>
- <th>С патчем</th>
- <th>Без патча</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>7.7.20</td>
- <td>397</td>
- <td>174 549</td>
- </tr>
- <tr>
- <td>7.7.21</td>
- <td>383</td>
- <td>53 995</td>
- </tr>
- <tr>
- <td>7.7.22</td>
- <td>483</td>
- <td>3 995</td>
- </tr>
- </tbody>
- </table>
- </section>
- <address class="contacts">
- Автор: <a href="https://twitter.com/@doochik">@doochik</a><br>
- С++ разработчик<br>
- Электронная почта: <a href="mailto:doochik@yandex-team.ru">doochik@yandex-team.ru</a><br>
- Компания: <a href="https://www.yandex.ru">Яндекс</a>
- </address>
- </article>
- <hr>
- <section class="content">
- <h3>Комментарии (4):</h3>
- <ul>
- <li>
- <strong>Mogaika (<a href="mailto:mogaika@yandex-team.ru">mogaika@yandex-team.ru</a>)
- <time datetime="2014-11-30 17:05">30 ноября 2014 в 17:05</time></strong><br>
- А можете привести сравнение, на сколько быстрее грузится lite версия?
- </li>
- <li>
- <strong>JIguse (<a href="mailto:mrawesome@yandex.ru">mrawesome@yandex.ru</a>)
- <time datetime="2014-11-29 21:30">29 ноября 2014 в 21:30</time></strong>
- <br>
- Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми
- подробностями о внутренней работе сервисов.
- </li>
- <li>
- <strong>Brister (<a href="mailto:brist89@yandex-team.ru">brist89@yandex-team.ru</a>)
- <time datetime="2014-11-24 13:13">24 ноября 2014 в 13:13</time></strong><br>
- (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех).<br>
- Получается значение от нуля до единицы, которое, видимо, лучше всего показывает,
- хорошо или плохо работает почта.<br>
- наверное все-таки от 0.5 до 1
- </li>
- <li>
- <strong>alexeimois (<a href="mailto:test@yandex.ru">test@yandex.ru</a>)
- <time datetime="2014-11-22 17:35">22 ноября 2014 в 17:35</time></strong><br>
- Мы измеряем скорость загрузки с помощью Яндекс.Метрики:<br>
- <a href="https://help.yandex.ru/metrika/reports/monitoring_timing.xml">
- help.yandex.ru/metrika/reports/monitoring_timing.xml
- </a>
- </li>
- </ul>
- </section>
- </main>
- <footer>
- <div class="content">
- <small>© Яндекс, <a href="mailto:help@yandex.ru">help@yandex.ru</a>, Хохрякова, 10</small>
- </div>
- </footer>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement