You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: case-study.md
+19-7Lines changed: 19 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -68,25 +68,37 @@
68
68
69
69
### Находка №5
70
70
-`ruby-prof` в режиме `Graph` показывает, что точкой роста является `27.07% 16.32% 3.99 2.41 0.00 1.58 846230 <Class::Date>#parse`, это строка `user.sessions.map{|s| s['date']}.map {|d| Date.parse(d)}.sort.reverse.map { |d| d.iso8601 }`
71
-
-вместо `Date.parse(d)` используем `Date.strptime(d, '%Y-%m-%d')` (заранее известен формат). Даты часто повторяются, используем мемоизацию для уже распаршенных дат.
72
-
- время выполнения программы для 1кк входных данных сократилось с 10с до с 7.8c
71
+
-поскольку строки уже находятся в формате iso8601, это позволяет использовать строки для сортировки не преобразуя их в даты: убираем парсинг дат, с последующим преобразованием в iso8601.
72
+
- время выполнения программы для 1кк входных данных сократилось с 10с до с 7.5c
73
73
- исправленная проблема перестала быть главной точкой роста.
74
74
75
75
### Находка №6
76
76
-`ruby-prof` в режиме `CallStack` показывает, что точкой роста является `7.20% (15.82%) Array#include? [846230 calls, 846230 total]`
77
77
- вместо формирования уникальных браузеров через each, сделаем `uniqueBrowsers = sessions.map { |session| session['browser'] }.uniq`.
78
-
- время выполнения программы для 1кк входных данных сократилось с 7.8 до с 7.3c
78
+
- время выполнения программы для 1кк входных данных сократилось с 7.5 до с 6.9c
79
79
- исправленная проблема перестала быть главной точкой роста.
80
80
81
81
### Находка №7
82
-
-`ruby-prof` в режиме `CallStack` показывает, что точкой роста является `2.22% (14.64%) String#upcase [846230 calls, 2331849 total]` в контексте `45.05% (45.05%) Object#collect_stats_from_users`
83
-
- вместо фомирования `upcase` версий браузеров трижды для каждого юзера, сделаем это единожды в начале итерации: `upcased_browsers = user.sessions.map{|s| s['browser'].upcase }` и далее будем переиспользовать этот результат.
84
-
- время выполнения программы для 1кк входных данных сократилось с 7.3 до с 6.9c
82
+
-`ruby-prof` в режиме `CallGrind` показывает, что точкой роста является `Object::collect_stats_from_users`-> `Array::map`->`String::upcase`
83
+
- поскольку используется только `upcase` версия браузера, при парсинге сессия сразу записываем `upcase` версию. Поскольку не так много видов браузеров относительно общего количества сессий, используем мемоизацию.
84
+
- время выполнения программы для 1кк входных данных сократилось с 6.9 до с 6.4c
85
+
- исправленная проблема перестала быть главной точкой роста.
86
+
87
+
### Находка №8
88
+
-`ruby-prof` в режиме `CallGrind` показывает, что точкой роста является `Array::each`->`Array::each`->`Object::parse_session`->`String::split`
89
+
- делаем `split` только единожды для каждой строчки, в `parse_user`, `parse_session` передаем уже массив, а не строку
90
+
- время выполнения программы для 1кк входных данных сократилось с 6.4 до с 5.4c
91
+
- исправленная проблема перестала быть главной точкой роста.
92
+
93
+
### Находка №9
94
+
-`ruby-prof` в режиме `CallGrind` показывает, что точкой роста является `Object::collect_stats_from_users`->`Array::each`->`Array::map`->`String::to_i`
95
+
- поскольку используется только целочисленное значение `time`, делаем преобразование `to_i` один раз в `parse_session`, а не дважды в `collect_stats_from_users`.
96
+
- время выполнения программы для 1кк входных данных сократилось с 5.4 до с 5c
85
97
- исправленная проблема перестала быть главной точкой роста.
86
98
87
99
## Результаты
88
100
В результате проделанной оптимизации наконец удалось обработать файл с данными.
89
-
Удалось улучшить метрику системы с 4.7 дней до 13 секунд и уложиться в заданный бюджет.
101
+
Удалось улучшить метрику системы с 4.7 дней до 24 секунд и уложиться в заданный бюджет.
90
102
91
103
## Защита от регрессии производительности
92
104
Для защиты от потери достигнутого прогресса при дальнейших изменениях программы добавил два теста: прогон на полных данных до 15 секунд, проверка на линейную асимптотику
0 commit comments