Conversation
f6010a9 to
8e5e268
Compare
8e5e268 to
1d15e77
Compare
|
|
||
| ## Формирование метрики | ||
| Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: | ||
| Время выполнения программы. |
There was a problem hiding this comment.
Да, но есть момент, что время работы программы ещё зависит от объёма данных.
Нам тут получается нужно несколько разных метрик. Каждая из которых служит одной цели: на текущей итерации оценить насколько текущее изменения полезно
| Программа поставлялась с тестом. Выполнение этого теста в фидбек-лупе позволяет не допустить изменения логики программы при оптимизации. | ||
|
|
||
| ## Feedback-Loop | ||
| Для того, чтобы иметь возможность быстро проверять гипотезы я выстроил эффективный `feedback-loop`, который позволил мне получать обратную связь по эффективности сделанных изменений за *время, которое у вас получилось* |
| ### находка №1 Многократная итерация объекта sessions для создания users_objects | ||
| - callstack из ruby-prof | ||
| - Одной итерацией собрать необходимые данные в объекте sessions_by_user | ||
| - Время выполнения приложения на 15т строк сократилась 7.5 секунд до 0.9 секунд |
There was a problem hiding this comment.
главное, что сложность O(N^2) -> O(N)
| ### находка №2 Неэффективный алгоритм с многократными проверками для сбора unique_browsers. | ||
| - callstack из ruby-prof | ||
| - Было принято решение заменить неэффективный алгоритм с многократными проверками на более оптимизированное решение, использующее встроенные методы Ruby | ||
| - Время выполнения приложения на 15т строк сократилась 0.9 секунд до 0.6 секунд |
There was a problem hiding this comment.
лучше при профилировании в подобных задачах, которые очень долгие давать программе хотя бы несколько секунд покрутиться. Так profile будет более приближен к реальности
|
|
||
| ### Находка №3: Неэффективное добавление элементов в массивы с использованием оператора конкатенации | ||
| - callstack из ruby-prof | ||
| - Было принято решение заменить неэффективное добавление элементов в массивы с помощью оператора + на использование метода << (shovel operator). Дополнительно была применена конструкция case для улучшения читаемости и производительности. |
There was a problem hiding this comment.
лучше стараться избегать соблазна сделат что-то "дополнительно" в одну итерацию.
как только мы сделали больше одного изменения, мы сразу перестаём понимать какое как сработало
| ### Находка №5: Избыточное использование хешей для представления сессий | ||
| - callstack из ruby-prof | ||
| - Анализ профилировщика показал, что создание и обработка хешей в методе parse_session занимают значительное время, особенно при большом количестве сессий. Это связано с накладными расходами на создание объектов хешей и доступ к их ключам. | ||
| - Было принято решение заменить использование хешей на Struct для представления сессий. Struct предоставляет более легковесную и быструю структуру для хранения данных с фиксированными ключами, что уменьшает время создания объектов и ускоряет доступ к их атрибутам. |
There was a problem hiding this comment.
ого, кажется впервые вижу такую оптимизацию в этом задании; интересно!
|
|
||
| ## Результаты | ||
| В результате проделанной оптимизации наконец удалось обработать файл с данными. | ||
| Удалось улучшить метрику системы с более чем 15 минут обработки файла до 30 секунд и уложиться в заданный бюджет. |
There was a problem hiding this comment.
там ближе к неделе, чем к 15 минутам
| describe 'Task-1 Performance' do | ||
| describe '#work method' do | ||
| it 'completes the operation within 30 seconds' do | ||
| expect { work(file_name: "data_large.txt", progress_bar: false) }.to perform_under(30).sec |
There was a problem hiding this comment.
👍
пользуясь тем, что у нас сложность стала O(N) можно было бы сделать тест побыстрее. Взять например 1% данных и 1% времени
| } | ||
| end | ||
|
|
||
| Session = Struct.new(:user_id, :session_id, :browser, :time, :date) |
| browser = session['browser'] | ||
| uniqueBrowsers += [browser] if uniqueBrowsers.all? { |b| b != browser } | ||
| end | ||
| unique_browsers = sessions.map { |session| session['browser'] }.uniq |
No description provided.