Skip to content

Commit 07a891e

Browse files
authored
1 parent 93e6324 commit 07a891e

File tree

1 file changed

+315
-0
lines changed

1 file changed

+315
-0
lines changed

index.html

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,320 @@
44
<meta charset="utf-8">
55
</head>
66
<body>
7+
<h2>
8+
Блог компании <span style="color: red;">Я</span>ндекс.
9+
<h2>
10+
<section>
11+
<article>
12+
<h1>
13+
<span style="color: red;">Я</span>НДЕКС.ПОЧТА: КАК МЫ ИЗМЕРЯЕМ СКОРОСТЬ ЗАГРУЗКИ И УЛУЧШАЕМ ЕЁ
14+
<h1>
15+
16+
<p>
17+
Если ваш сайт медленно грузится, вы рискуете тем, что люди не оценят ни то,
18+
какой он красивый, ни то, какой он удобный. Никому не понравится, когда все
19+
тормозит. Мы регулярно добавляем в <span style="color: red;">Я</span>ндекс.Почту новую функциональность,
20+
иногда — исправляем ошибки, а это значит, у нас постоянно появляются новый код
21+
и новая логика. Всё это напрямую влияет на скорость работы интерфейса.
22+
</p>
23+
</article>
24+
<article>
25+
<h2>
26+
Что мы измеряем
27+
</h2>
28+
29+
<ul>Этапы первой загрузки:</ul>
30+
<li>подготовка;</li>
31+
<li>загрузка статики (HTTP-запрос и парсинг);</li>
32+
<li>исполнение модулей;</li>
33+
<li>инициализация базовых объектов</li>
34+
<li>отрисовка.</li>
35+
36+
<ul>Этапы отрисовки любой страницы:</ul>
37+
<li>подготовка к запросу на сервер;</li>
38+
<li>запрос данных с сервера;</li>
39+
<li>шаблонизация;</li>
40+
<li>обновление DOM.</li>
41+
42+
</article>
43+
44+
<hr>
45+
46+
<p>
47+
<blockquote>— «Ок, теперь у нас есть метрики, мы можем отправить их на сервер» - говорим мы</blockquote>
48+
</p>
49+
<p>
50+
<blockquote>— «Что же дальше?» - вопрошаете вы</blockquote>
51+
</p>
52+
<p>
53+
<blockquote>— «А давай построим график!» - отвечаем мы</blockquote>
54+
</p>
55+
<p>
56+
<blockquote>— «А что будем считать?» - уточняете вы</blockquote>
57+
</p>
58+
59+
<p>
60+
Как вы знаете, <em>медиана</em> – это серединное, а не среднее значение в выборке.
61+
</p>
62+
<p>
63+
Если у нас имеются числа 1, 2, 2, 3, 8, 10, 20, то медиана – 3, а среднее – 6,5.
64+
</p>
65+
<p>
66+
В общем случае медиана отлично показывает, сколько
67+
грузится средний пользователь.
68+
</p>
69+
70+
<p>
71+
В случае ускорения или замедления медиана, конечно, изменится. Но она не может
72+
рассказать, сколько пользователей ускорилось, а сколько замедлилось.
73+
</p>
74+
75+
<p>
76+
<strong><span translate="no">APDEX</span></strong> – метрика, которая сразу говорит: хорошо или плохо. Метрика
77+
работает очень просто. Мы выбираем временной интервал [0; t], такой, что если
78+
время показа страницы попало в него, то пользователь счастлив. Берем еще один
79+
интервал, (t; 4t] (в четыре раза больше первого), и считаем, что если страница
80+
показана за это время, то пользователь в целом удовлетворен скоростью работы,
81+
но уже не настолько счастлив. И применяем формулу:
82+
</p>
83+
84+
<p>
85+
(кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех).
86+
Получается значение от нуля до единицы, которое, видимо, лучше всего показывает,
87+
хорошо или плохо работает почта.
88+
</p>
89+
90+
<h2>
91+
Как мы измеряем
92+
</h2>
93+
94+
<p>
95+
Сейчас модуль обновления сам логирует все свои стадии, и можно легко понять
96+
причину замедления: медленнее стал отвечать сервер либо слишком долго
97+
выполняется <span translate="no">JavaScript</span>. Выглядит это примерно так:
98+
</p>
99+
<p>
100+
<code>
101+
this.timings['look-ma-im-start'] = Date.now();
102+
this.timings['look-ma-finish'] = Date.now();
103+
</code>
104+
</p>
105+
106+
<p>
107+
C помощью <code>Date.now()</code> мы получаем текущее время. Все тайминги собираются и при
108+
отправке рассчитываются. На этапах разница между <span translate="no">“end”</span> и <span translate="no">“start”</span> не считается,
109+
а все вычисления производятся в конце:
110+
</p>
111+
112+
<p>
113+
<code>
114+
var totalTime = this.timings['look-ma-finish'] - this.timings['look-ma-im-start'];
115+
</code>
116+
</p>
117+
118+
<p>
119+
И на сервер прилетают подобные записи:
120+
</p>
121+
122+
<p>
123+
<samp>
124+
serverResponse=50&domUpdate=60
125+
</samp>
126+
</p>
127+
128+
<h2>
129+
Как мы ускоряем
130+
</h2>
131+
132+
<p>
133+
Чтобы снизить время загрузки почты при выходе новых версий,
134+
мы уже делаем следующее:
135+
</p>
136+
137+
<ul>
138+
<li>включаем gzip;</li>
139+
<li>выставляем заголовки кэширования;</li>
140+
<li>фризим CSS, JS, шаблоны и картинки;</li>
141+
<li>используем CDN;</li>
142+
</ul>
143+
144+
<p>
145+
Мы подумали:<blockquote>«А что если хранить где-то старую версию файлов, а при выходе новой
146+
передавать только <span translate="no">diff</span> между ней и той, которая сохранена у пользователя?»</blockquote>
147+
В браузере же останется просто наложить патч на клиенте.
148+
</p>
149+
150+
<p>
151+
На самое деле эта идея не нова. Уже существуют стандарты для HTTP — например,<span translate="no">
152+
RFC 3229 «Delta encoding in HTTP»</span> и <span translate="no">«Google SDHC»</span>, — но по разным причинам они
153+
не получили должного распространения в браузерах и на серверах.
154+
</p>
155+
156+
<p>
157+
Мы же решили сделать свой аналог на JS. Чтобы реализовать этот метод обновления,
158+
начали искать реализации <span translate="no">diff</span> на <span translate="no">JS</span>. На популярных хостингах кода нашли
159+
библиотеки:
160+
</p>
161+
162+
<ul>
163+
<li>VCDiff</li>
164+
<li>google-diff-patch-match</li>
165+
</ul>
166+
167+
<p>
168+
Для окончательного выбора библиотеки нам нужно сравнить:
169+
</p>
170+
171+
<pre>
172+
Библиотека | IE 9 | Opera 12
173+
---------- | ---- | --------
174+
vcdiff | 8 | 5
175+
google diff | 1363 | 76
176+
</pre>
177+
178+
<p>
179+
После того как мы определились с библиотекой для диффа, нужно определиться с тем,
180+
где и как хранить статику на клиенте.
181+
</p>
182+
183+
<p>
184+
Формат файла с патчами для проекта выглядит так:
185+
</p>
186+
187+
<p>
188+
<code>
189+
[
190+
{
191+
"k": "jane.css",
192+
"p": [patch],
193+
"s": 4554
194+
},
195+
{
196+
"k": "jane.css",
197+
"p": [patch],
198+
"s": 4554
199+
}
200+
]
201+
</code>
202+
</p>
203+
204+
<p>
205+
То есть это обычный массив из объектов. Каждый объект — отдельный ресурс. У
206+
каждого объекта есть три свойства. <span translate="no">k</span> — названия ключа в <span translate="no">localStorage</span> для этого
207+
ресурса. <span translate="no">p</span> — патч для ресурса, который сгенерировал <span translate="no">vcdiff. s</span> — чексумма для
208+
ресурса актуальной версии, чтобы потом можно было проверить правильность
209+
наложения патча на клиенте. Чексумма вычисляется по алгоритму Флетчера.
210+
</p>
211+
212+
<p>
213+
<strong>Алгоритм Бройдена — Флетчера — Гольдфарба — Шанно (BFGS)</strong>
214+
— итерационный метод численной оптимизации,<wbr> предназначенный для
215+
нахождения локального максимума/минимума нелинейного функционала
216+
без ограничений.
217+
</p>
218+
219+
<p>
220+
Почему именно алгоритм Флетчера, а не другие популярные алгоритмы вроде:
221+
</p>
222+
223+
<p>
224+
<stong>CRC16/32</stong> - алгоритм нахождения контрольной суммы, предназначенный для проверки
225+
целостности данных
226+
</p>
227+
228+
<p>
229+
<strong>md5</strong> - 128-битный алгоритм хеширования. Предназначен для создания «отпечатков»
230+
или дайджестов сообщения произвольной длины и последующей проверки
231+
их подлинности.
232+
</p>
233+
234+
<p>
235+
Потому что он быстрый, компактный и легок в реализации.
236+
</p>
237+
238+
<h2>
239+
Итог
240+
</h2>
241+
242+
<p>
243+
Фактически мы экономим 80-90% трафика. Размер загружаемой статитки в байтах:
244+
</p>
245+
246+
<pre>
247+
Релиз | С патчем | Без патча
248+
7.7.20 | 397 | 174 549
249+
7.7.21 | 383 | 53 995
250+
7.7.22 | 483 | 3 995
251+
</pre>
252+
</section>
253+
254+
<address>
255+
<p>
256+
Автор: @doochik
257+
</p>
258+
<p>
259+
С++ разработик
260+
</p>
261+
<p>
262+
Электронная почта: (<a href="mailto:[email protected]">[email protected]</a>)
263+
</p>
264+
<p>
265+
Компания: <span style="color: red;">Я</span>ндекс
266+
</p>
267+
</address>
268+
269+
<h3>
270+
Комментарии (3):
271+
</h3>
272+
273+
<section>
274+
<header>
275+
- Mogaika ([email protected]) 30 ноября 2014 в 17:05
276+
</header>
277+
<article>
278+
А можете привести сравнение, на сколько быстрее грузится lite версия?
279+
</article>
280+
</section>
281+
282+
<section>
283+
<header>
284+
- JIguse ([email protected]) 29 ноября 2014 в 21:30
285+
</header>
286+
<article>
287+
Спасибо за статью, познавательно. Здорово, что Яндекс делится некоторыми
288+
подробностями о внутренней работе сервисов.
289+
</article>
290+
</section>
291+
<section>
292+
<header>
293+
- Brister ([email protected]) 24 ноября 2014 в 13:13
294+
</header>
295+
<article>
296+
<p>
297+
(кол-во счастливых пользователей + кол-во удовлетворенных / 2) / (кол-во всех).
298+
Получается значение от нуля до единицы, которое, видимо, лучше всего показывает,
299+
хорошо или плохо работает почта.
300+
</p>
301+
302+
<p>
303+
наверное все-таки от 0.5 до 1
304+
</p>
305+
</article>
306+
</section>
307+
<section>
308+
<header>
309+
- alexeimois ([email protected]) 22 ноября 2014 в 17:35
310+
</header>
311+
<article>
312+
Мы измеряем скорость загрузки с помощью <span style="color: red;">Я</span>ндекс.Метрики:
313+
<a href = "help.yandex.ru/metrika/reports/monitoring_timing.xml">metrika</a>
314+
</article>
315+
</section>
316+
317+
<footer>
318+
<p>
319+
© <span style="color: red;">Я</span>ндекс, [email protected], Хохрякова, 10
320+
</p>
321+
</footer>
7322
</body>
8323
</html>

0 commit comments

Comments
 (0)