-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Homework solution #150
base: master
Are you sure you want to change the base?
Homework solution #150
Changes from all commits
c27da02
0a9e95b
2d6426e
8011778
08f0506
5b80d94
b9a3e81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.DS_Store | ||
data_large.txt | ||
data_prof.txt | ||
result.json |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Case-study оптимизации | ||
|
||
## Актуальная проблема | ||
В нашем проекте возникла серьёзная проблема. | ||
|
||
Необходимо было обработать файл с данными, чуть больше ста мегабайт. | ||
|
||
У нас уже была программа на `ruby`, которая умела делать нужную обработку. | ||
|
||
Она успешно работала на файлах размером пару мегабайт, но для большого файла она работала слишком долго, и не было понятно, закончит ли она вообще работу за какое-то разумное время. | ||
|
||
Я решил исправить эту проблему, оптимизировав эту программу. | ||
|
||
## Формирование метрики | ||
Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: Время выполнения программы. | ||
|
||
## Гарантия корректности работы оптимизированной программы | ||
Программа поставлялась с тестом. Выполнение этого теста в фидбек-лупе позволяет не допустить изменения логики программы при оптимизации. | ||
|
||
## Feedback-Loop | ||
Для того, чтобы иметь возможность быстро проверять гипотезы я выстроил эффективный `feedback-loop`, который позволил мне получать обратную связь по эффективности сделанных изменений за 10-20 секунд. | ||
|
||
Вот как я построил `feedback_loop`: Создавал файл с N строк, чтобы программа могла выполнятся 10-20 секунд | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
## Вникаем в детали системы, чтобы найти главные точки роста | ||
Для того, чтобы найти "точки роста" для оптимизации я воспользовался RubyProf, с отчетами в виде Graph и CallStack | ||
|
||
Вот какие проблемы удалось найти и решить | ||
|
||
### Ваша находка №1 | ||
- CallStack показал что программа 94.55% времени тратит на Array#select. С помощью Graph стало понятно что много времени тратиться на поиск сессий пользователя. | ||
- Для решения данной проблемы, перед тем как проходится по пользователям, нужно подготовить данные users_sessions в виде хэша, ключем будет id пользователя, а значение массив его сессий, тогда мы один раз пройдемся по sessions | ||
- Время выполнения программы уменьшилось с ~20 секунд до ~1 секунды, при входных данных в 30000 строк. Время выполнения программы на большом объёме данных больше 30 секунд. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. тут самое главное, что асимптотику сильно лучше сделали |
||
- Отчет профилировщика стал указывать на другие проблемы, главная точкой роста изменилась. | ||
|
||
### Ваша находка №2 | ||
- При объёме данных в 200к строк CallStack показал что программа 56.29% времени тратит на Array#+. С помощью Graph стало понятно что много времени тратиться на формирования списка пользователей (users). | ||
- Рекомундуется использовать Array#concat (https://github.com/fastruby/fast-ruby?tab=readme-ov-file#arrayconcat-vs-array-code) | ||
- Время выполнения программы особо не изменилось. | ||
- Отчет профилировщика стал указывать на другие проблемы, главная точкой роста изменилась. | ||
|
||
### Ваша находка №3 | ||
- При объёме данных в 200к строк CallStack показал что программа 56.92% времени тратит на Array#+. С помощью Graph стало понятно что много времени тратиться на формирования списка сессий (sessions). | ||
- Рекомундуется использовать Array#concat (https://github.com/fastruby/fast-ruby?tab=readme-ov-file#arrayconcat-vs-array-code) | ||
- Время выполнения программы уменьшилось с ~14 секунд до ~6 секунд, при входных данных в 200к строк. Время выполнения программы на большом объёме данных больше 30 секунд. | ||
- Отчет профилировщика стал указывать на другие проблемы, главная точкой роста изменилась. | ||
|
||
### Ваша находка №4 | ||
- При объёме данных в 400к строк CallStack показал что программа 52.94% времени тратит на Array#all?. С помощью Graph стало понятно что много времени тратиться на проверку уникальности браузера (uniqueBrowsers). | ||
- Для этих данных лучше всего подойдет Set. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
- Время выполнения программы уменьшилось с ~15 секунд до ~7 секунд, при входных данных в 400к строк. Время выполнения программы на большом объёме данных больше 30 секунд. | ||
- Отчет профилировщика стал указывать на другие проблемы, главная точкой роста изменилась. | ||
|
||
### Ваша находка №5 | ||
- При объёме данных в 700к строк CallStack показал что программа 53.64% времени тратит на Array#+. С помощью Graph стало понятно что много времени тратиться на формирования списка пользователей (users_objects). | ||
- Рекомундуется использовать Array#concat (https://github.com/fastruby/fast-ruby?tab=readme-ov-file#arrayconcat-vs-array-code) | ||
- Время выполнения программы уменьшилось с ~18 секунд до ~9 секунд, при входных данных в 700к строк. Время выполнения программы на большом объёме данных стало меньше 30 секунд. | ||
- Отчет профилировщика стал указывать на другие проблемы, главная точкой роста изменилась. Сейчас большая часть времени тратиться на Array#map в методе collect_stats_from_users. | ||
|
||
## Результаты | ||
В результате проделанной оптимизации наконец удалось обработать файл с данными. | ||
Удалось улучшить метрику системы с более 15 минут до менее 30 секунд и уложиться в заданный бюджет. | ||
|
||
## Защита от регрессии производительности | ||
Для защиты от потери достигнутого прогресса при дальнейших изменениях программы был создан performance тест. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍