From e077bca015f58b2bea4aa6d0eaef2cacb00180f2 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Wed, 19 Oct 2016 23:59:09 +0600 Subject: [PATCH 01/19] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=B2=D0=B0=D1=80=D0=B8=D0=B0=D0=BD=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) diff --git a/index.html b/index.html index d810ba7..ab9d41e 100644 --- a/index.html +++ b/index.html @@ -1,8 +1,262 @@ + Блог компании Яндекс. + +
+

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ

+
+
+

+ Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, + какой он красивый, ни то, какой он удобный. Никому не понравится, когда все + тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность, + иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код + и новая логика. Всё это напрямую влияет на скорость работы интерфейса. +

+ +
+

Что мы измеряем

+

Этапы первой загрузки:

+
    +
  • подготовка;
  • +
  • загрузка статики (HTTP-запрос и парсинг);
  • +
  • исполнение модулей;
  • +
  • инициализация базовых объектов;
  • +
  • отрисовка.
  • +
+

Этапы отрисовки любой страницы:

+
    +
  • подготовка к запросу на сервер;
  • +
  • запрос данных с сервера;
  • +
  • шаблонизация;
  • +
  • обновление DOM.
  • +
+

+ — Ок, теперь у нас есть метрики, мы можем отправить их на сервер - говорим мы
+ — Что же дальше? - вопрошаете вы
+ — А давай построим график! - отвечаем мы
+ — А что будем считать? - уточняете вы +

+

+ Как вы знаете, медиана – это серединное, а не среднее значение в выборке. + Если у нас имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5. + В общем случае медиана отлично показывает, сколько грузится средний пользователь. +

+

+ В случае ускорения или замедления медиана, конечно, изменится. Но она не может + рассказать, сколько пользователей ускорилось, а сколько замедлилось. +

+

+ APDEX – метрика, которая сразу говорит: хорошо или плохо. Метрика + работает очень просто. Мы выбираем временной интервал [0; t], такой, что если + время показа страницы попало в него, то пользователь счастлив. Берем еще один + интервал, (t; 4t] (в четыре раза больше первого), и считаем, что если страница + показана за это время, то пользователь в целом удовлетворен скоростью работы, + но уже не настолько счастлив. И применяем формулу: +

+

+ (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). +

+

+ Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, + хорошо или плохо работает почта. +

+
+
+

Как мы измеряем

+

+ Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять + причину замедления: медленнее стал отвечать сервер либо слишком долго + выполняется JavaScript. Выглядит это примерно так: +

+

+ this.timings['look-ma-im-start'] = Date.now();
+ this.timings['look-ma-finish'] = Date.now(); +

+

+ C помощью Date.now() мы получаем текущее время. Все тайминги собираются и при + отправке рассчитываются. На этапах разница между “end” и “start” не считается, + а все вычисления производятся в конце: +

+

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];

+

И на сервер прилетают подобные записи:

+

serverResponse=50&domUpdate=60

+
+
+

Как мы ускоряем

+

Чтобы снизить время загрузки почты при выходе новых версий,мы уже делаем следующее:

+
    +
  1. включаем gzip;
  2. +
  3. выставляем заголовки кэширования;
  4. +
  5. фризим CSS, JS, шаблоны и картинки;
  6. +
  7. используем CDN;
  8. +
+

+ Мы подумали: «А что если хранить где-то старую версию файлов, а при выходе новой + передавать только diff между ней и той, которая сохранена у пользователя?» + В браузере же останется просто наложить патч на клиенте. +

+

+ На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например, + RFC 3229 «Delta encoding in HTTP» и «Google SDHC», — но по разным причинам они + не получили должного распространения в браузерах и на серверах. +

+

+ Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления, + начали искать реализации diff на JS. На популярных хостингах кода нашли + библиотеки: +

+

- VCDiff
+ - google-diff-patch-match

+

Для окончательного выбора библиотеки нам нужно сравнить:

+ + + + + + + + + + + + + + + + +
БиблиотекаIE 9Opera 12
vcdiff85
google diff136376
+

+ После того как мы определились с библиотекой для диффа, нужно определиться с тем, + где и как хранить статику на клиенте. +

+

Формат файла с патчами для проекта выглядит так:

+
+				
+					[
+						{
+							"k": "jane.css",
+							"p": [patch],
+							"s": 4554
+						},
+						{
+							"k": "jane.css",
+							"p": [patch],
+							"s": 4554
+						}
+					]
+				
+			
+

+ То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У + каждого объекта есть три свойства. k — названия ключа в localStorage для этого + ресурса. p — патч для ресурса, который сгенерировал vcdiff. s — чексумма для + ресурса актуальной версии, чтобы потом можно было проверить правильность + наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера. +

+

+ Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн + (BFGS) + — итерационный метод численной оптимизации, предназначенный для + нахождения локального максимума/минимума нелинейного функционала + без ограничений. +

+
+ дано ε, x0
+ инициализировать Η0
+ k = 0
+ while ||∇ƒk|| > ε
+    найти направление + pk = -Ck∇ ƒk
+    вычислить + xk+1 = xk + αk pk, + αk удовлетворяет условиям Вольфе
+    обозначить + sk = xk+1 - xk и + yk = ∇ ƒk+1 - ∇ ƒk
+    вычислить + Ck+1
+    k = k + 1
+ end +
+

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

+

+ CRC16/32 - алгоритм нахождения контрольной суммы, + предназначенный для проверки целостности данных +

+

+ md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» + или дайджестов сообщения произвольной длины и последующей проверки + их подлинности. +

+

Потому что он быстрый, компактный и легок в реализации.

+
+
+

Итог

+

Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:

+ + + + + + + + + + + + + + + + + + + + + +
РелизС патчем Без патча
7.7.20397174 549
7.7.2138353 995
7.7.224833 995
+

+ Автор: @doochik
+ С++ разработик
+ Электронная почта: (doochik@yandex-team.ru)
+ Компания: Яндекс +

+

Комментарии (3):

+

- Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

+

А можете привести сравнение, на сколько быстрее грузится lite версия?

+

- JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

+

+ Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми + подробностями о внутренней работе сервисов. +

+

- Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

+

+ (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). + Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, + хорошо или плохо работает почта. +

+

наверное все-таки от 0.5 до 1

+

- alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

+

+ Мы измеряем скорость загрузки с помощью Яндекс.Метрики: + + help.yandex.ru/metrika/reports/monitoring_timing.xml + +

+
+
+ From 757ba2457b530a8892461d7a31313d7fc65ab664 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:09:34 +0600 Subject: [PATCH 02/19] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D1=82=D0=B0=D0=B1?= =?UTF-8?q?=D0=BB=D0=B8=D1=86=D0=B0=D1=85=20=D0=B8=20=D1=81=D0=B8=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D0=BA=D1=81=D0=B8=D1=81=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index ab9d41e..7d77759 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,10 @@ background-color: #E6E6E6; padding-left: 10px; } + + table { + cellpadding="5" + } @@ -22,7 +26,7 @@

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗА иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код и новая логика. Всё это напрямую влияет на скорость работы интерфейса.

- + Яндекс

Что мы измеряем

Этапы первой загрузки:

@@ -118,7 +122,7 @@

Как мы ускоряем

- VCDiff
- google-diff-patch-match

Для окончательного выбора библиотеки нам нужно сравнить:

- +
@@ -173,7 +177,7 @@

Как мы ускоряем

дано ε, x0
инициализировать Η0
- k = 0
+ k = 0
while ||∇ƒk|| > ε
   найти направление pk = -Ck∇ ƒk
@@ -185,7 +189,7 @@

Как мы ускоряем

yk = ∇ ƒk+1 - ∇ ƒk
   вычислить Ck+1
-    k = k + 1
+    k = k + 1
end

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

@@ -203,7 +207,7 @@

Как мы ускоряем

Итог

Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:

-
Библиотека IE 9
+
From eaa9a545a5bfb9b74202f9cd3f3add0524b9b8b5 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:13:28 +0600 Subject: [PATCH 03/19] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/index.css b/index.css index e69de29..a4ed0cb 100644 --- a/index.css +++ b/index.css @@ -0,0 +1,8 @@ +#BFGS { + background-color: #E6E6E6; + padding-left: 10px; +} + +table { + cellpadding="5" +} From 4dcb5d5ffab31b4c8b2dbdfc1560646fcc57df50 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:15:54 +0600 Subject: [PATCH 04/19] =?UTF-8?q?=D0=A1=D0=B8=D0=BD=D1=82=D0=B0=D0=BA?= =?UTF-8?q?=D1=81=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/index.html b/index.html index 7d77759..c9dd819 100644 --- a/index.html +++ b/index.html @@ -2,17 +2,7 @@ Блог компании Яндекс. - - +
From ef746039ed2f2dd82ce1e603bd1538de2169e0ff Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:18:32 +0600 Subject: [PATCH 05/19] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.css b/index.css index a4ed0cb..f61c7de 100644 --- a/index.css +++ b/index.css @@ -2,7 +2,3 @@ background-color: #E6E6E6; padding-left: 10px; } - -table { - cellpadding="5" -} From a66970dd3b4268a281cfa1f5e4184ba35f6bd942 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:23:37 +0600 Subject: [PATCH 06/19] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20CSS=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.css | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.css b/index.css index f61c7de..6185a1f 100644 --- a/index.css +++ b/index.css @@ -1,4 +1,5 @@ -#BFGS { - background-color: #E6E6E6; - padding-left: 10px; +#BFGS +{ + background-color: #e6e6e6; + padding-left: 10px; } From 3def21d86e92bf92e2d823bf8031695bb090b249 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:26:46 +0600 Subject: [PATCH 07/19] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20CSS=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.css b/index.css index 6185a1f..a5b3f60 100644 --- a/index.css +++ b/index.css @@ -1,5 +1,5 @@ -#BFGS +#BFGS { background-color: #e6e6e6; - padding-left: 10px; + padding-left: 10px; } From 3304df1e7e5b630a2ec10d6310bb466a077d8db3 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:30:37 +0600 Subject: [PATCH 08/19] =?UTF-8?q?=D0=9E=D1=87=D0=B8=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D0=BB=D1=8C=20CSS=20=D0=B7=D0=B0=20=D0=BD=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=BD=D0=BE=D1=81=D1=82=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.css | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/index.css b/index.css index a5b3f60..d3f5a12 100644 --- a/index.css +++ b/index.css @@ -1,5 +1 @@ -#BFGS -{ - background-color: #e6e6e6; - padding-left: 10px; -} + From ea2f86d81bd344ca7b89272df1715fb3ce61ec2a Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:35:42 +0600 Subject: [PATCH 09/19] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D1=82=D0=B5=D0=B3=D0=B8=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index c9dd819..76b22f6 100644 --- a/index.html +++ b/index.html @@ -19,7 +19,7 @@

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗА Яндекс

Что мы измеряем

-

Этапы первой загрузки:

+

Этапы первой загрузки:

  • подготовка;
  • загрузка статики (HTTP-запрос и парсинг);
  • @@ -27,7 +27,7 @@

    Что мы измеряем

  • инициализация базовых объектов;
  • отрисовка.
-

Этапы отрисовки любой страницы:

+

Этапы отрисовки любой страницы:

  • подготовка к запросу на сервер;
  • запрос данных с сервера;
  • @@ -83,7 +83,7 @@

    Как мы измеряем

    var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];

    И на сервер прилетают подобные записи:

    -

    serverResponse=50&domUpdate=60

    +

    serverResponse=50&domUpdate=60

Как мы ускоряем

From 8e7509a920ca195e9f21c646a3c7ff430963e87b Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:43:51 +0600 Subject: [PATCH 10/19] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D1=82=D0=B5=D0=B3=D0=BE=D0=B2=20=D0=B8=20?= =?UTF-8?q?=D0=B0=D1=82=D1=82=D1=80=D0=B8=D0=B1=D1=83=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 56 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/index.html b/index.html index 76b22f6..6d96c1b 100644 --- a/index.html +++ b/index.html @@ -5,10 +5,10 @@ -
+

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ

-
+

Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, какой он красивый, ни то, какой он удобный. Никому не понравится, когда все @@ -16,7 +16,7 @@

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗА иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код и новая логика. Всё это напрямую влияет на скорость работы интерфейса.

- Яндекс + Яндекс

Что мы измеряем

Этапы первой загрузки:

@@ -58,7 +58,7 @@

Что мы измеряем

но уже не настолько счастлив. И применяем формулу:

- (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). + (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех).

Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, @@ -73,17 +73,17 @@

Как мы измеряем

выполняется JavaScript. Выглядит это примерно так:

- this.timings['look-ma-im-start'] = Date.now();
- this.timings['look-ma-finish'] = Date.now(); + this.timings['look-ma-im-start'] = Date.now();
+ this.timings['look-ma-finish'] = Date.now();

C помощью Date.now() мы получаем текущее время. Все тайминги собираются и при отправке рассчитываются. На этапах разница между “end” и “start” не считается, а все вычисления производятся в конце:

-

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];

+

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];>

И на сервер прилетают подобные записи:

-

serverResponse=50&domUpdate=60

+

serverResponse=50&domUpdate=60

Как мы ускоряем

@@ -109,8 +109,10 @@

Как мы ускоряем

начали искать реализации diff на JS. На популярных хостингах кода нашли библиотеки:

-

- VCDiff
- - google-diff-patch-match

+

+ - VCDiff
+ - google-diff-patch-match +

Для окончательного выбора библиотеки нам нужно сравнить:

Релиз С патчем
@@ -158,37 +160,37 @@

Как мы ускоряем

наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера.

- Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн - (BFGS) + Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн + (BFGS) — итерационный метод численной оптимизации, предназначенный для нахождения локального максимума/минимума нелинейного функционала без ограничений.

- дано ε, x0
- инициализировать Η0
- k = 0
- while ||∇ƒk|| > ε
+ дано ε, x0
+ инициализировать Η0
+ k = 0
+ while ||∇ƒk|| > ε
   найти направление - pk = -Ck∇ ƒk
+ pk = -Ck∇ ƒk
   вычислить - xk+1 = xk + αk pk, - αk удовлетворяет условиям Вольфе
+ xk+1 = xk + αk pk, + αk удовлетворяет условиям Вольфе
   обозначить - sk = xk+1 - xk и - yk = ∇ ƒk+1 - ∇ ƒk
+ sk = xk+1 - xk и + yk = ∇ ƒk+1 - ∇ ƒk
   вычислить - Ck+1
-    k = k + 1
- end + Ck+1
+    k = k + 1
+ end

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

- CRC16/32 - алгоритм нахождения контрольной суммы, + CRC16/32 - алгоритм нахождения контрольной суммы, предназначенный для проверки целостности данных

- md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» + md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» или дайджестов сообщения произвольной длины и последующей проверки их подлинности.

@@ -250,7 +252,7 @@

Итог

- © Яндекс, help@yandex.ru, Хохрякова, 10 + © Яндекс, help@yandex.ru, Хохрякова, 10
From c3c70e9ccb4a8d2d2b926aa43f393a7833868d41 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:52:13 +0600 Subject: [PATCH 11/19] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D0=B8=D0=BD=D1=82=D0=B0?= =?UTF-8?q?=D0=BA=D1=81=D0=B8=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 505 ++++++++++++++++++++++++++--------------------------- 1 file changed, 252 insertions(+), 253 deletions(-) diff --git a/index.html b/index.html index 6d96c1b..773a046 100644 --- a/index.html +++ b/index.html @@ -1,258 +1,257 @@ - - Блог компании Яндекс. - - - -
-

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ

-
-
-

- Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, - какой он красивый, ни то, какой он удобный. Никому не понравится, когда все - тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность, - иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код - и новая логика. Всё это напрямую влияет на скорость работы интерфейса. -

- Яндекс -
-

Что мы измеряем

-

Этапы первой загрузки:

-
    -
  • подготовка;
  • -
  • загрузка статики (HTTP-запрос и парсинг);
  • -
  • исполнение модулей;
  • -
  • инициализация базовых объектов;
  • -
  • отрисовка.
  • -
-

Этапы отрисовки любой страницы:

-
    -
  • подготовка к запросу на сервер;
  • -
  • запрос данных с сервера;
  • -
  • шаблонизация;
  • -
  • обновление DOM.
  • -
+ + Блог компании Яндекс. + + +
+

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ

+
+

- — Ок, теперь у нас есть метрики, мы можем отправить их на сервер - говорим мы
- — Что же дальше? - вопрошаете вы
- — А давай построим график! - отвечаем мы
- — А что будем считать? - уточняете вы + Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, + какой он красивый, ни то, какой он удобный. Никому не понравится, когда все + тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность, + иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код + и новая логика. Всё это напрямую влияет на скорость работы интерфейса.

-

- Как вы знаете, медиана – это серединное, а не среднее значение в выборке. - Если у нас имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5. - В общем случае медиана отлично показывает, сколько грузится средний пользователь. -

-

- В случае ускорения или замедления медиана, конечно, изменится. Но она не может - рассказать, сколько пользователей ускорилось, а сколько замедлилось. -

-

- APDEX – метрика, которая сразу говорит: хорошо или плохо. Метрика - работает очень просто. Мы выбираем временной интервал [0; t], такой, что если - время показа страницы попало в него, то пользователь счастлив. Берем еще один - интервал, (t; 4t] (в четыре раза больше первого), и считаем, что если страница - показана за это время, то пользователь в целом удовлетворен скоростью работы, - но уже не настолько счастлив. И применяем формулу: -

-

- (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). -

-

- Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, - хорошо или плохо работает почта. -

-
-
-

Как мы измеряем

-

- Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять - причину замедления: медленнее стал отвечать сервер либо слишком долго - выполняется JavaScript. Выглядит это примерно так: -

-

- this.timings['look-ma-im-start'] = Date.now();
- this.timings['look-ma-finish'] = Date.now(); -

-

- C помощью Date.now() мы получаем текущее время. Все тайминги собираются и при - отправке рассчитываются. На этапах разница между “end” и “start” не считается, - а все вычисления производятся в конце: -

-

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];>

-

И на сервер прилетают подобные записи:

-

serverResponse=50&domUpdate=60

-
-
-

Как мы ускоряем

-

Чтобы снизить время загрузки почты при выходе новых версий,мы уже делаем следующее:

-
    -
  1. включаем gzip;
  2. -
  3. выставляем заголовки кэширования;
  4. -
  5. фризим CSS, JS, шаблоны и картинки;
  6. -
  7. используем CDN;
  8. -
-

- Мы подумали: «А что если хранить где-то старую версию файлов, а при выходе новой - передавать только diff между ней и той, которая сохранена у пользователя?» - В браузере же останется просто наложить патч на клиенте. -

-

- На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например, - RFC 3229 «Delta encoding in HTTP» и «Google SDHC», — но по разным причинам они - не получили должного распространения в браузерах и на серверах. -

-

- Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления, - начали искать реализации diff на JS. На популярных хостингах кода нашли - библиотеки: -

-

- - VCDiff
- - google-diff-patch-match -

-

Для окончательного выбора библиотеки нам нужно сравнить:

-
- - - - - - - - - - - - - - - -
БиблиотекаIE 9Opera 12
vcdiff85
google diff136376
-

- После того как мы определились с библиотекой для диффа, нужно определиться с тем, - где и как хранить статику на клиенте. -

-

Формат файла с патчами для проекта выглядит так:

-
-				
-					[
-						{
-							"k": "jane.css",
-							"p": [patch],
-							"s": 4554
-						},
-						{
-							"k": "jane.css",
-							"p": [patch],
-							"s": 4554
-						}
-					]
-				
-			
-

- То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У - каждого объекта есть три свойства. k — названия ключа в localStorage для этого - ресурса. p — патч для ресурса, который сгенерировал vcdiff. s — чексумма для - ресурса актуальной версии, чтобы потом можно было проверить правильность - наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера. -

-

- Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн - (BFGS) - — итерационный метод численной оптимизации, предназначенный для - нахождения локального максимума/минимума нелинейного функционала - без ограничений. -

-
- дано ε, x0
- инициализировать Η0
- k = 0
- while ||∇ƒk|| > ε
-    найти направление - pk = -Ck∇ ƒk
-    вычислить - xk+1 = xk + αk pk, - αk удовлетворяет условиям Вольфе
-    обозначить - sk = xk+1 - xk и - yk = ∇ ƒk+1 - ∇ ƒk
-    вычислить - Ck+1
-    k = k + 1
- end -
-

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

-

- CRC16/32 - алгоритм нахождения контрольной суммы, - предназначенный для проверки целостности данных -

-

- md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» - или дайджестов сообщения произвольной длины и последующей проверки - их подлинности. -

-

Потому что он быстрый, компактный и легок в реализации.

-
-
-

Итог

-

Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:

- - - - - - - - - - - - - - - - - - - - - -
РелизС патчем Без патча
7.7.20397174 549
7.7.2138353 995
7.7.224833 995
-

- Автор: @doochik
- С++ разработик
- Электронная почта: (doochik@yandex-team.ru)
- Компания: Яндекс -

-

Комментарии (3):

-

- Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

-

А можете привести сравнение, на сколько быстрее грузится lite версия?

-

- JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

-

- Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми - подробностями о внутренней работе сервисов. -

-

- Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

-

- (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). - Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, - хорошо или плохо работает почта. -

-

наверное все-таки от 0.5 до 1

-

- alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

-

- Мы измеряем скорость загрузки с помощью Яндекс.Метрики: - - help.yandex.ru/metrika/reports/monitoring_timing.xml - -

-
- -
- © Яндекс, help@yandex.ru, Хохрякова, 10 -
- + Яндекс +
+

Что мы измеряем

+

Этапы первой загрузки:

+
    +
  • подготовка;
  • +
  • загрузка статики (HTTP-запрос и парсинг);
  • +
  • исполнение модулей;
  • +
  • инициализация базовых объектов;
  • +
  • отрисовка.
  • +
+

Этапы отрисовки любой страницы:

+
    +
  • подготовка к запросу на сервер;
  • +
  • запрос данных с сервера;
  • +
  • шаблонизация;
  • +
  • обновление DOM.
  • +
+

+ — Ок, теперь у нас есть метрики, мы можем отправить их на сервер - говорим мы
+ — Что же дальше? - вопрошаете вы
+ — А давай построим график! - отвечаем мы
+ — А что будем считать? - уточняете вы +

+

+ Как вы знаете, медиана – это серединное, а не среднее значение в выборке. + Если у нас имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5. + В общем случае медиана отлично показывает, сколько грузится средний пользователь. +

+

+ В случае ускорения или замедления медиана, конечно, изменится. Но она не может + рассказать, сколько пользователей ускорилось, а сколько замедлилось. +

+

+ APDEX – метрика, которая сразу говорит: хорошо или плохо. Метрика + работает очень просто. Мы выбираем временной интервал [0; t], такой, что если + время показа страницы попало в него, то пользователь счастлив. Берем еще один + интервал, (t; 4t] (в четыре раза больше первого), и считаем, что если страница + показана за это время, то пользователь в целом удовлетворен скоростью работы, + но уже не настолько счастлив. И применяем формулу: +

+

+ (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). +

+

+ Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, + хорошо или плохо работает почта. +

+
+
+

Как мы измеряем

+

+ Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять + причину замедления: медленнее стал отвечать сервер либо слишком долго + выполняется JavaScript. Выглядит это примерно так: +

+

+ this.timings['look-ma-im-start'] = Date.now();
+ this.timings['look-ma-finish'] = Date.now(); +

+

+ C помощью Date.now() мы получаем текущее время. Все тайминги собираются и при + отправке рассчитываются. На этапах разница между “end” и “start” не считается, + а все вычисления производятся в конце: +

+

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];>

+

И на сервер прилетают подобные записи:

+

serverResponse=50&domUpdate=60

+
+
+

Как мы ускоряем

+

Чтобы снизить время загрузки почты при выходе новых версий,мы уже делаем следующее:

+
    +
  1. включаем gzip;
  2. +
  3. выставляем заголовки кэширования;
  4. +
  5. фризим CSS, JS, шаблоны и картинки;
  6. +
  7. используем CDN;
  8. +
+

+ Мы подумали: «А что если хранить где-то старую версию файлов, а при выходе новой + передавать только diff между ней и той, которая сохранена у пользователя?» + В браузере же останется просто наложить патч на клиенте. +

+

+ На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например, + RFC 3229 «Delta encoding in HTTP» и «Google SDHC», — но по разным причинам они + не получили должного распространения в браузерах и на серверах. +

+

+ Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления, + начали искать реализации diff на JS. На популярных хостингах кода нашли + библиотеки: +

+

+ - VCDiff
+ - google-diff-patch-match +

+

Для окончательного выбора библиотеки нам нужно сравнить:

+ + + + + + + + + + + + + + + + +
БиблиотекаIE 9Opera 12
vcdiff85
google diff136376
+

+ После того как мы определились с библиотекой для диффа, нужно определиться с тем, + где и как хранить статику на клиенте. +

+

Формат файла с патчами для проекта выглядит так:

+
+					
+						[
+							{
+								"k": "jane.css",
+								"p": [patch],
+								"s": 4554
+							},
+							{
+								"k": "jane.css",
+								"p": [patch],
+								"s": 4554
+							}
+						]
+					
+				
+

+ То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У + каждого объекта есть три свойства. k — названия ключа в localStorage для этого + ресурса. p — патч для ресурса, который сгенерировал vcdiff. s — чексумма для + ресурса актуальной версии, чтобы потом можно было проверить правильность + наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера. +

+

+ Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн + (BFGS) + — итерационный метод численной оптимизации, предназначенный для + нахождения локального максимума/минимума нелинейного функционала + без ограничений. +

+
+ дано ε, x0
+ инициализировать Η0
+ k = 0
+ while ||∇ƒk|| > ε
+    найти направление + pk = -Ck∇ ƒk
+    вычислить + xk+1 = xk + αk pk, + αk удовлетворяет условиям Вольфе
+    обозначить + sk = xk+1 - xk и + yk = ∇ ƒk+1 - ∇ ƒk
+    вычислить + Ck+1
+    k = k + 1
+ end +
+

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

+

+ CRC16/32 - алгоритм нахождения контрольной суммы, + предназначенный для проверки целостности данных +

+

+ md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» + или дайджестов сообщения произвольной длины и последующей проверки + их подлинности. +

+

Потому что он быстрый, компактный и легок в реализации.

+
+
+

Итог

+

Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:

+ + + + + + + + + + + + + + + + + + + + + +
РелизС патчем Без патча
7.7.20397174 549
7.7.2138353 995
7.7.224833 995
+

+ Автор: @doochik
+ С++ разработик
+ Электронная почта: (doochik@yandex-team.ru)
+ Компания: Яндекс +

+

Комментарии (3):

+

- Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

+

А можете привести сравнение, на сколько быстрее грузится lite версия?

+

- JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

+

+ Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми + подробностями о внутренней работе сервисов. +

+

- Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

+

+ (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). + Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, + хорошо или плохо работает почта. +

+

наверное все-таки от 0.5 до 1

+

- alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

+

+ Мы измеряем скорость загрузки с помощью Яндекс.Метрики: + + help.yandex.ru/metrika/reports/monitoring_timing.xml + +

+
+ +
+ © Яндекс, help@yandex.ru, Хохрякова, 10 +
+ From a74681d766f4023e3ee18b143d220d25e78d14ab Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:56:03 +0600 Subject: [PATCH 12/19] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6?= =?UTF-8?q?=D0=BD=D0=BE=D0=B5=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/index.html b/index.html index 773a046..2b59512 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,3 @@ - Блог компании Яндекс. From 451f90117bfdf461b679549cd28b214eda4ce281 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 00:58:27 +0600 Subject: [PATCH 13/19] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BE=D0=B1=D1=80=D0=B0=D1=82=D0=BD=D0=BE=20doctype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 2b59512..773a046 100644 --- a/index.html +++ b/index.html @@ -1,3 +1,4 @@ + Блог компании Яндекс. From a38e2860402ba26cf0fe57e45ce82e7c8769a391 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 01:20:32 +0600 Subject: [PATCH 14/19] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BF=D0=B0=D1=80=D1=83=20=D1=82=D0=B5=D0=B3=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 773a046..85a494e 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,7 @@

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗА

- Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, + Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, какой он красивый, ни то, какой он удобный. Никому не понравится, когда все тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность, иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код @@ -251,7 +251,7 @@

Итог

- © Яндекс, help@yandex.ru, Хохрякова, 10 +
© Яндекс, help@yandex.ru, Хохрякова, 10
From a994bcea7d902fa272e19e51bafb8430a1ad7bb1 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 01:41:40 +0600 Subject: [PATCH 15/19] =?UTF-8?q?=D0=A1=D0=B8=D0=BD=D1=82=D0=B0=D0=BA?= =?UTF-8?q?=D1=81=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 505 +++++++++++++++++++++++++++-------------------------- 1 file changed, 253 insertions(+), 252 deletions(-) diff --git a/index.html b/index.html index 85a494e..240dc8c 100644 --- a/index.html +++ b/index.html @@ -1,257 +1,258 @@ - - Блог компании Яндекс. - - -
-

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ

-
-
+ + + Блог компании Яндекс. + + +
+

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ

+
+
+

+ Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, + какой он красивый, ни то, какой он удобный. Никому не понравится, когда все + тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность, + иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код + и новая логика. Всё это напрямую влияет на скорость работы интерфейса. +

+ Яндекс +
+

Что мы измеряем

+

Этапы первой загрузки:

+
    +
  • подготовка;
  • +
  • загрузка статики (HTTP-запрос и парсинг);
  • +
  • исполнение модулей;
  • +
  • инициализация базовых объектов;
  • +
  • отрисовка.
  • +
+

Этапы отрисовки любой страницы:

+
    +
  • подготовка к запросу на сервер;
  • +
  • запрос данных с сервера;
  • +
  • шаблонизация;
  • +
  • обновление DOM.
  • +

- Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то, - какой он красивый, ни то, какой он удобный. Никому не понравится, когда все - тормозит. Мы регулярно добавляем в Яндекс.Почту новую функциональность, - иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код - и новая логика. Всё это напрямую влияет на скорость работы интерфейса. + — Ок, теперь у нас есть метрики, мы можем отправить их на сервер - говорим мы
+ — Что же дальше? - вопрошаете вы
+ — А давай построим график! - отвечаем мы
+ — А что будем считать? - уточняете вы

- Яндекс -
-

Что мы измеряем

-

Этапы первой загрузки:

-
    -
  • подготовка;
  • -
  • загрузка статики (HTTP-запрос и парсинг);
  • -
  • исполнение модулей;
  • -
  • инициализация базовых объектов;
  • -
  • отрисовка.
  • -
-

Этапы отрисовки любой страницы:

-
    -
  • подготовка к запросу на сервер;
  • -
  • запрос данных с сервера;
  • -
  • шаблонизация;
  • -
  • обновление DOM.
  • -
-

- — Ок, теперь у нас есть метрики, мы можем отправить их на сервер - говорим мы
- — Что же дальше? - вопрошаете вы
- — А давай построим график! - отвечаем мы
- — А что будем считать? - уточняете вы -

-

- Как вы знаете, медиана – это серединное, а не среднее значение в выборке. - Если у нас имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5. - В общем случае медиана отлично показывает, сколько грузится средний пользователь. -

-

- В случае ускорения или замедления медиана, конечно, изменится. Но она не может - рассказать, сколько пользователей ускорилось, а сколько замедлилось. -

-

- APDEX – метрика, которая сразу говорит: хорошо или плохо. Метрика - работает очень просто. Мы выбираем временной интервал [0; t], такой, что если - время показа страницы попало в него, то пользователь счастлив. Берем еще один - интервал, (t; 4t] (в четыре раза больше первого), и считаем, что если страница - показана за это время, то пользователь в целом удовлетворен скоростью работы, - но уже не настолько счастлив. И применяем формулу: -

-

- (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). -

-

- Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, - хорошо или плохо работает почта. -

-
-
-

Как мы измеряем

-

- Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять - причину замедления: медленнее стал отвечать сервер либо слишком долго - выполняется JavaScript. Выглядит это примерно так: -

-

- this.timings['look-ma-im-start'] = Date.now();
- this.timings['look-ma-finish'] = Date.now(); -

-

- C помощью Date.now() мы получаем текущее время. Все тайминги собираются и при - отправке рассчитываются. На этапах разница между “end” и “start” не считается, - а все вычисления производятся в конце: -

-

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];>

-

И на сервер прилетают подобные записи:

-

serverResponse=50&domUpdate=60

-
-
-

Как мы ускоряем

-

Чтобы снизить время загрузки почты при выходе новых версий,мы уже делаем следующее:

-
    -
  1. включаем gzip;
  2. -
  3. выставляем заголовки кэширования;
  4. -
  5. фризим CSS, JS, шаблоны и картинки;
  6. -
  7. используем CDN;
  8. -
-

- Мы подумали: «А что если хранить где-то старую версию файлов, а при выходе новой - передавать только diff между ней и той, которая сохранена у пользователя?» - В браузере же останется просто наложить патч на клиенте. -

-

- На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например, - RFC 3229 «Delta encoding in HTTP» и «Google SDHC», — но по разным причинам они - не получили должного распространения в браузерах и на серверах. -

-

- Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления, - начали искать реализации diff на JS. На популярных хостингах кода нашли - библиотеки: -

-

- - VCDiff
- - google-diff-patch-match -

-

Для окончательного выбора библиотеки нам нужно сравнить:

- - - - - - - - - - - - - - - - -
БиблиотекаIE 9Opera 12
vcdiff85
google diff136376
-

- После того как мы определились с библиотекой для диффа, нужно определиться с тем, - где и как хранить статику на клиенте. -

-

Формат файла с патчами для проекта выглядит так:

-
-					
-						[
-							{
-								"k": "jane.css",
-								"p": [patch],
-								"s": 4554
-							},
-							{
-								"k": "jane.css",
-								"p": [patch],
-								"s": 4554
-							}
-						]
-					
-				
-

- То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У - каждого объекта есть три свойства. k — названия ключа в localStorage для этого - ресурса. p — патч для ресурса, который сгенерировал vcdiff. s — чексумма для - ресурса актуальной версии, чтобы потом можно было проверить правильность - наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера. -

-

- Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн - (BFGS) - — итерационный метод численной оптимизации, предназначенный для - нахождения локального максимума/минимума нелинейного функционала - без ограничений. -

-
- дано ε, x0
- инициализировать Η0
- k = 0
- while ||∇ƒk|| > ε
-    найти направление - pk = -Ck∇ ƒk
-    вычислить - xk+1 = xk + αk pk, - αk удовлетворяет условиям Вольфе
-    обозначить - sk = xk+1 - xk и - yk = ∇ ƒk+1 - ∇ ƒk
-    вычислить - Ck+1
-    k = k + 1
- end -
-

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

-

- CRC16/32 - алгоритм нахождения контрольной суммы, - предназначенный для проверки целостности данных -

-

- md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» - или дайджестов сообщения произвольной длины и последующей проверки - их подлинности. -

-

Потому что он быстрый, компактный и легок в реализации.

-
-
-

Итог

-

Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:

- - - - - - - - - - - - - - - - - - - - - -
РелизС патчем Без патча
7.7.20397174 549
7.7.2138353 995
7.7.224833 995
-

- Автор: @doochik
- С++ разработик
- Электронная почта: (doochik@yandex-team.ru)
- Компания: Яндекс -

-

Комментарии (3):

-

- Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

-

А можете привести сравнение, на сколько быстрее грузится lite версия?

-

- JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

-

- Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми - подробностями о внутренней работе сервисов. -

-

- Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

-

- (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). - Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, - хорошо или плохо работает почта. -

-

наверное все-таки от 0.5 до 1

-

- alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

-

- Мы измеряем скорость загрузки с помощью Яндекс.Метрики: - - help.yandex.ru/metrika/reports/monitoring_timing.xml - -

-
-
-
-
© Яндекс, help@yandex.ru, Хохрякова, 10
-
- +

+ Как вы знаете, медиана – это серединное, а не среднее значение в выборке. + Если у нас имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5. + В общем случае медиана отлично показывает, сколько грузится средний пользователь. +

+

+ В случае ускорения или замедления медиана, конечно, изменится. Но она не может + рассказать, сколько пользователей ускорилось, а сколько замедлилось. +

+

+ APDEX – метрика, которая сразу говорит: хорошо или плохо. Метрика + работает очень просто. Мы выбираем временной интервал [0; t], такой, что если + время показа страницы попало в него, то пользователь счастлив. Берем еще один + интервал, (t; 4t] (в четыре раза больше первого), и считаем, что если страница + показана за это время, то пользователь в целом удовлетворен скоростью работы, + но уже не настолько счастлив. И применяем формулу: +

+

+ (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). +

+

+ Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, + хорошо или плохо работает почта. +

+ +
+

Как мы измеряем

+

+ Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять + причину замедления: медленнее стал отвечать сервер либо слишком долго + выполняется JavaScript. Выглядит это примерно так: +

+

+ this.timings['look-ma-im-start'] = Date.now();
+ this.timings['look-ma-finish'] = Date.now(); +

+

+ C помощью Date.now() мы получаем текущее время. Все тайминги собираются и при + отправке рассчитываются. На этапах разница между “end” и “start” не считается, + а все вычисления производятся в конце: +

+

var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];>

+

И на сервер прилетают подобные записи:

+

serverResponse=50&domUpdate=60

+
+
+

Как мы ускоряем

+

Чтобы снизить время загрузки почты при выходе новых версий,мы уже делаем следующее:

+
    +
  1. включаем gzip;
  2. +
  3. выставляем заголовки кэширования;
  4. +
  5. фризим CSS, JS, шаблоны и картинки;
  6. +
  7. используем CDN;
  8. +
+

+ Мы подумали: «А что если хранить где-то старую версию файлов, а при выходе новой + передавать только diff между ней и той, которая сохранена у пользователя?» + В браузере же останется просто наложить патч на клиенте. +

+

+ На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например, + RFC 3229 «Delta encoding in HTTP» и «Google SDHC», — но по разным причинам они + не получили должного распространения в браузерах и на серверах. +

+

+ Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления, + начали искать реализации diff на JS. На популярных хостингах кода нашли + библиотеки: +

+

+ - VCDiff
+ - google-diff-patch-match +

+

Для окончательного выбора библиотеки нам нужно сравнить:

+ + + + + + + + + + + + + + + + +
БиблиотекаIE 9Opera 12
vcdiff85
google diff136376
+

+ После того как мы определились с библиотекой для диффа, нужно определиться с тем, + где и как хранить статику на клиенте. +

+

Формат файла с патчами для проекта выглядит так:

+
+				
+					[
+						{
+							"k": "jane.css",
+							"p": [patch],
+							"s": 4554
+						},
+						{
+							"k": "jane.css",
+							"p": [patch],
+							"s": 4554
+						}
+					]
+				
+			
+

+ То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У + каждого объекта есть три свойства. k — названия ключа в localStorage для этого + ресурса. p — патч для ресурса, который сгенерировал vcdiff. s — чексумма для + ресурса актуальной версии, чтобы потом можно было проверить правильность + наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера. +

+

+ Алгоритм Бройдена — Флетчера — Гольдфарба — Шанн + (BFGS) + — итерационный метод численной оптимизации, предназначенный для + нахождения локального максимума/минимума нелинейного функционала + без ограничений. +

+
+ дано ε, x0
+ инициализировать Η0
+ k = 0
+ while ||∇ƒk|| > ε
+    найти направление + pk = -Ck∇ ƒk
+    вычислить + xk+1 = xk + αk pk, + αk удовлетворяет условиям Вольфе
+    обозначить + sk = xk+1 - xk и + yk = ∇ ƒk+1 - ∇ ƒk
+    вычислить + Ck+1
+    k = k + 1
+ end +
+

Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:

+

+ CRC16/32 - алгоритм нахождения контрольной суммы, + предназначенный для проверки целостности данных +

+

+ md5 - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков» + или дайджестов сообщения произвольной длины и последующей проверки + их подлинности. +

+

Потому что он быстрый, компактный и легок в реализации.

+
+
+

Итог

+

Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:

+ + + + + + + + + + + + + + + + + + + + + +
РелизС патчем Без патча
7.7.20397174 549
7.7.2138353 995
7.7.224833 995
+

+ Автор: @doochik
+ С++ разработик
+ Электронная почта: (doochik@yandex-team.ru)
+ Компания: Яндекс +

+

Комментарии (3):

+

- Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

+

А можете привести сравнение, на сколько быстрее грузится lite версия?

+

- JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

+

+ Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми + подробностями о внутренней работе сервисов. +

+

- Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

+

+ (кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). + Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, + хорошо или плохо работает почта. +

+

наверное все-таки от 0.5 до 1

+

- alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

+

+ Мы измеряем скорость загрузки с помощью Яндекс.Метрики: + + help.yandex.ru/metrika/reports/monitoring_timing.xml + +

+
+
+
+
© Яндекс, help@yandex.ru, Хохрякова, 10
+
+ From 640bfbe89126199141779d1fef7887ba09200708 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 02:00:22 +0600 Subject: [PATCH 16/19] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=81=D0=BF=D0=B5=D1=86=D1=81=D0=B8=D0=BC=D0=B2?= =?UTF-8?q?=D0=BE=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 240dc8c..fd9d5a2 100644 --- a/index.html +++ b/index.html @@ -170,7 +170,7 @@

Как мы ускоряем

дано ε, x0
инициализировать Η0
k = 0
- while ||∇ƒk|| > ε
+ while ||∇ƒk|| > ε
   найти направление pk = -Ck∇ ƒk
   вычислить From 561a45269bdfa17b44f2d63305436b528daf6401 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 02:15:55 +0600 Subject: [PATCH 17/19] =?UTF-8?q?=D0=A1=D0=B8=D0=BD=D1=82=D0=B0=D0=BA?= =?UTF-8?q?=D1=81=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index fd9d5a2..65f3b08 100644 --- a/index.html +++ b/index.html @@ -202,7 +202,7 @@

Итог

- + @@ -228,24 +228,24 @@

Итог

Компания: Яндекс

Комментарии (3):

-

- Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

+

Mogaika (mogaika@yandex-team.ru) 30 ноября 2014 в 17:05

А можете привести сравнение, на сколько быстрее грузится lite версия?

-

- JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

+

JIguse (mrawesome@yandex.ru) 29 ноября 2014 в 21:30

Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми подробностями о внутренней работе сервисов.

-

- Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

+

Brister (brist89@yandex-team.ru) 24 ноября 2014 в 13:13

(кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех). Получается значение от нуля до единицы, которое, видимо, лучше всего показывает, хорошо или плохо работает почта.

наверное все-таки от 0.5 до 1

-

- alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

+

alexeimois (test@yandex.ru) 22 ноября 2014 в 17:35

Мы измеряем скорость загрузки с помощью Яндекс.Метрики: - + help.yandex.ru/metrika/reports/monitoring_timing.xml

From 330747328e15c86fb9978f040fea73855c0a43b8 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 02:28:19 +0600 Subject: [PATCH 18/19] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B1?= =?UTF-8?q?=D0=B5=D0=BB=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 65f3b08..2f57527 100644 --- a/index.html +++ b/index.html @@ -18,7 +18,7 @@

ЯНДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗА

Яндекс
-

Что мы измеряем

+

Что мы измеряем

Этапы первой загрузки:

  • подготовка;
  • From b949fc9e1636dfa04f78c7b941c3a1a5797ea4e2 Mon Sep 17 00:00:00 2001 From: alexanderkine Date: Thu, 20 Oct 2016 02:44:48 +0600 Subject: [PATCH 19/19] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D0=BF=D0=B5=D1=86=D1=81=D0=B8=D0=BC=D0=B2=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 2f57527..ac5d67d 100644 --- a/index.html +++ b/index.html @@ -172,13 +172,13 @@

    Как мы ускоряем

    k = 0
    while ||∇ƒk|| > ε
       найти направление - pk = -Ck∇ ƒk
    + pk = —Ck∇ ƒk
       вычислить xk+1 = xk + αk pk, αk удовлетворяет условиям Вольфе
       обозначить - sk = xk+1 - xk и - yk = ∇ ƒk+1 - ∇ ƒk
    + sk = xk+1 — xk и + yk = ∇ ƒk+1 — ∇ ƒk
       вычислить Ck+1
       k = k + 1

РелизС патчем С патчем Без патча