-
Notifications
You must be signed in to change notification settings - Fork 24
pustserg homework1 #12
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
Open
pustserg
wants to merge
3
commits into
spajic:master
Choose a base branch
from
pustserg:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,8 @@ | |
| Я решил исправить эту проблему, оптимизировав эту программу. | ||
|
|
||
| ## Формирование метрики | ||
| Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: *тут ваша метрика* | ||
| Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: в первую очередь нас интересует время работы программы, пока она отрабатывает за "бесконечное время" оптимизация памяти преждевременна | ||
| Хочу не потеряв в удобности поддержки кода оптимизировать код чтобы программа работала хотя бы в пределах минуты | ||
|
|
||
| ## Гарантия корректности работы оптимизированной программы | ||
| Программа поставлялась с тестом. Выполнение этого теста позволяет не допустить изменения логики программы при оптимизации. | ||
|
|
@@ -23,22 +24,156 @@ | |
| Вот как я построил `feedback_loop`: *как вы построили feedback_loop* | ||
|
|
||
| ## Вникаем в детали системы, чтобы найти 20% точек роста | ||
| Для того, чтобы найти "точки роста" для оптимизации я воспользовался *инструментами, которыми вы воспользовались* | ||
| Первой очевидной точкой раста на первый взгляд кажется чтение файла, но даже в первоначальном состоянии это | ||
| занимает около 1,5 секунды что в рамках работы всей программы не так много. | ||
|
|
||
| Для того, чтобы найти "точки роста" для оптимизации я воспользовался | ||
| - Посмотрел с помощью benchmark как растет потребление памяти при обработке 100, 1000, 10000, 50000 строк из файла, без построения отчета | ||
| получились такие результаты: | ||
| 100 - 0.0003s | ||
| 1000 - 0.005s | ||
| 10000 - 0.5s | ||
| 50000 - 6.02s программа не отработала | ||
| 100000 - 21.8945s программа не отработала | ||
| Окей, время работы растет очень сильно, но 6 секунд на парсинг строк и в несколько раз больше времени на построение отчета говорят что | ||
| основные проблемы не в парсинге строк. Этот момент тоже надо оптимизировать, но позже, пока приоритеты на оптимизацию выглядят так | ||
|
|
||
| 1. ??? | ||
|
Owner
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. Парсинг строк | ||
| 3. Потоковое чтение из файла | ||
|
|
||
| Проверяем каждый этап построения отчета на массиве в 10к строк | ||
| Больше всего времени уходит на построение массива из инстанос класса User | ||
| парсинг строк - 0.4936 | ||
| поиск уникальных браузеров - 0.0604 | ||
| Подсчёт количества уникальных браузеров - 0.0604 | ||
| Перечислить уникальные браузеры в алфавитном порядке через запятую и капсом - 0.005 | ||
| сколько всего сессий + 0.1847 | ||
| сколько всего времени + 0.0638 | ||
| самая длинная сессия + 0.0067 | ||
| браузеры через запятую + 0.0104 | ||
| Хоть раз использовал IE? + 0.0075 | ||
| Всегда использовал только Хром? + 0.006 | ||
| даты сессий в порядке убывания через запятую + 0.0596 | ||
|
|
||
| массив из User - 1.4759 | ||
|
|
||
| Проверяем на 20000 строк | ||
| парсинг строк - 0.9174 | ||
| поиск уникальных браузеров - 0.1074 | ||
| Подсчёт количества уникальных браузеров - 0.0604 | ||
| Перечислить уникальные браузеры в алфавитном порядке через запятую и капсом - 0.009 | ||
| сколько всего сессий + 0.0047 | ||
| сколько всего времени + 0.0131 | ||
| самая длинная сессия + 0.0128 | ||
| браузеры через запятую + 0.0232 | ||
| Хоть раз использовал IE? + 0.018 | ||
| Всегда использовал только Хром? + 0.0135 | ||
| даты сессий в порядке убывания через запятую + 0.1147 | ||
|
|
||
| массив User = 9.5216 | ||
|
|
||
|
|
||
| Очевидная проблема в генерации массива инстансов User. | ||
| Список кандидатов на оптимизацию выглядит так | ||
| 1. Построение массива юзеров | ||
| 2. Парсинг строк | ||
| 3. Построчное чтение файла | ||
|
|
||
| Очевидная проблема внутри генерации массива это поиск сессий по юзеру, если заранее сделать | ||
| группировку по user['id'] то можно избавиться от большого количества поисков | ||
| проверяем на 20000 строк все становится намного лучше | ||
| массив строится за 0.0181 секунды. | ||
|
|
||
| Можно пробовать 50000 строк | ||
| Парсинг строк - 5.9629 сек | ||
| Построение массива - 0.2721 | ||
|
|
||
| 100000 строк | ||
| Парсинг строк - 22.8494 сек | ||
| Построение массива - 0.9219 сек | ||
|
|
||
| Убираем лимит строк | ||
| 3250940 строк все еще не рабоает | ||
|
|
||
| В коде который парсит строки и разбивает их на 2 массива есть очевидная проблема в месте | ||
| где складываются массивы `users = users + [parse_user(line)]`, замена на `users.push(parse_user(line))` | ||
| явно улучшит ситуацию | ||
| пробуем | ||
|
|
||
| 100000 строк | ||
| Парсинг строк - 0.3815 сек | ||
| Построение массива - 1.6567 сек | ||
|
|
||
| 200000 строк | ||
| Парсинг строк - 1.079 сек | ||
| Построение массива - 4.9811 сек | ||
|
|
||
| 500000 строк | ||
| Парсинг строк - 2.7817 сек | ||
| Построение массива - 27.1264 сек | ||
| Подсчет количества уникальных браузеров - 2.7305 сек | ||
|
|
||
| 1 000 000 строк | ||
| Парсинг строк - 6.7363 сек | ||
| Построение массива - долго | ||
| Подсчет количества уникальных браузеров - 5.1087 сек | ||
|
|
||
| очевидно что надо улучшать построение массива юзеров | ||
| тоже меняем на `users_objects.push(user_object)` | ||
|
|
||
| 1 000 000 строк | ||
| Парсинг строк - 5.4842 сек | ||
| Построение массива - 0.6537 | ||
| Подсчет количества уникальных браузеров - 5.1087 сек | ||
|
|
||
| 2 000 000 строк | ||
| Парсинг строк - 14.5464 сек | ||
| Построение массива - 1.5422 | ||
| Подсчет количества уникальных браузеров - 11.0065 сек | ||
| Подсчет количества всех браузеров - 6.2511 | ||
|
|
||
| Смотрим внимательно на подсчет браузеров по сессиям | ||
| Для подсчета уникальных браузеров нам не нужен сам массив браузеров, переписываем на array#count | ||
| получили уменьшение времени с 11 сек до 1.0845 | ||
| Для вывода всех браузеров объединяем 2 подряд map в один и сортировку делаем после uniq | ||
| потребляемое время уменьшилось с 6 секунд до 2.9063 | ||
| неидеально, но сейчас проблема в другом | ||
|
|
||
| 2 000 000 записей | ||
| парсинг строк - 14.2793 | ||
| поиск уникальных браузеров - 1.0389 | ||
| Перечислить уникальные браузеры в алфавитном порядке через запятую и капсом - 2.9063 | ||
| сколько всего сессий + 2.9591 | ||
| сколько всего времени + 2.3199 | ||
| самая длинная сессия + 2.6779 | ||
| браузеры через запятую + 7.2522 | ||
| Хоть раз использовал IE? + 2.5836 | ||
| Всегда использовал только Хром? + 4.4826 | ||
| даты сессий в порядке убывания через запятую + 18.4876 | ||
|
|
||
| Очень много времени занимает вывод дат сессий, смотрим подробнее | ||
| если сделать допущение что все даты сессий в файле изначально записаны в формате | ||
| iso8601 (а если это лог нашей программы то мы можем на это влиять), то можно | ||
|
Owner
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. 👍 |
||
| сразу сортировать строки. | ||
| Сделав так получаем время работы этой статистики - 4.3849 | ||
|
|
||
| Пробуем убрать лимит на количество строк | ||
| программа отработала за 1 мин 49 сек 💪, 🤟, 🍾 | ||
|
Owner
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. 👍 👍 |
||
| Окей, отработала и уже хорошо, но надо найти способы еще ее ускорить | ||
| Больше всего времени сейчас занимает разбор считанных строк из файла, пробуем считывать файл построчно | ||
| 28,4398 лучше не стало | ||
| Пробуем убрать дополнительный split внутри parse_session и parse_user | ||
| 19.6525 очевидно что лучше. | ||
| Совсем очевидных проблем кажется что нет, надо запускать профайлеры памяти | ||
|
|
||
| RubyProf подсказал еще места которые позволили довести время работы программы до 80-90 секунд | ||
|
|
||
| Вот какие проблемы удалось найти и решить | ||
|
|
||
| ### Ваша находка №1 | ||
| О вашей находке №1 | ||
|
|
||
| ### Ваша находка №2 | ||
| О вашей находке №2 | ||
|
|
||
| ### Ваша находка №X | ||
| О вашей находке №X | ||
|
|
||
| ## Результаты | ||
| В результате проделанной оптимизации наконец удалось обработать файл с данными. | ||
| Удалось улучшить метрику системы с *того, что у вас было в начале, до того, что получилось в конце* | ||
| Удалось улучшить метрику системы с бесконечного времени, до < 2 минут. Изначальная цель "выйти из 1 минуты" не достигнута, | ||
| но отчетом по крайней мере можно пользоваться | ||
|
|
||
| *Какими ещё результами можете поделиться* | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| class User | ||
| attr_reader :attributes, :sessions | ||
|
|
||
| def initialize(attributes:, sessions:) | ||
| @attributes = attributes | ||
| @sessions = sessions | ||
| end | ||
| end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
👍