Conversation
| Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: *тут ваша метрика* | ||
| Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: | ||
| - Определил глобальну метрику - время выполнения программы на data_large файле. Бюджет - 3с. | ||
| - Т.к. работать с такими большими данными неэффективно, решил создать несколько файлов с 10_000, 25_000, 50_000, 100_000 и 200_000 строк. |
There was a problem hiding this comment.
да-да, по сути метрику, которую вам бы хотелось, вы не можете реально вычислить
поэтому приходится вводить промежуточные метрики (время для обработки файла x, y, z); они нам нужны на каждом шаге оптимизации чтобы понять насколько изменение было полезным
| * 50000 - "time":13.97,"gc_count":352,"memory":"147 MB" | ||
| * 100000 - "time":55.02,"gc_count":1290,"memory":"261 MB" | ||
| * 200000 - "time":229.75,"gc_count":4968,"memory":"180 MB" | ||
| > 55,02/13,97 ~ 4; 229,75/55,02 ~ 4 - асимптотика времени работы программы составляет квадратичную то есть время работы растёт пропорционально квадрату размера обрабатываемого файла O(n^2). Дал приблизительную оценку времени выполнения файла в 3 млн строк - 15ч. |
| Для того, чтобы иметь возможность быстро проверять гипотезы я выстроил эффективный `feedback-loop`, который позволил мне получать обратную связь по эффективности сделанных изменений за *время, которое у вас получилось* | ||
|
|
||
| Вот как я построил `feedback_loop`: *как вы построили feedback_loop* | ||
| Для того, чтобы иметь возможность быстро проверять гипотезы я выстроил эффективный `feedback-loop`, который позволил мне получать обратную связь по эффективности сделанных изменений за около 15 минут, так как аытался использовать различгые отчеты |
There was a problem hiding this comment.
время фидбек-лупа я скорее имею в виду это то сколько вам прихоидтся "тупо ждать" результата
то есть если вы сделали какое-то изменение и на проверку того, что стало лучше/хуже через минут 10 это очень плохо, потому что уже теряется фокус, начинается группировка изменений в одну итерацию и тд
| - как изменился отчёт профилировщика - исправленная проблема перестала быть главной точкой роста? | ||
| - Отчет ruby-prof flat показал 70.78% времени выполнения на Array#select | ||
| - Проблема была в формировании юзер сессий отдеьлным селектом по каждому юзеру. Чтобы избежать этого решил сгруппировать | ||
| сессии по user_id до итерирования по юзерам. |
There was a problem hiding this comment.
главное тут исправилась асимпототика с O(N^2) на O(N)
по идее тут можно было бы заново оценить асимптотику
и тогда можно было бы по идее даже задаться какой-то аппроксимацией а-ля если 3М - 30 сек, то надо уложиться 300К в 1сек и тогда должно быть норм
| Оценил бенчмарком время выполнения на 200_000 строк(1.96с). Принял решение создать файл для тестов на | ||
| 400_000 строк("time":5.11,"gc_count":542,"memory":"561 MB") для более точной оценки точек роста. | ||
| Оценил ассимпототику(400_000 - 5.11, 200_000 - 2.1, 100_000 - 0.9) - уже больше похоже на линейную зависимость. | ||
| Оптимистически предполагаю, что достижения бюджета в 3с для 400_000 строк должно хватить, для достижения основного бюджета. |
| - Для поиска главной точки роста решил использовать stackprof. Большую часть времени забирал на себя Array#each, но | ||
| я предположил что надо смотреть на то что конкретно в этом блоке тратится больше времени. Заметил что 55.66% времени | ||
| в этом блоке занимает Array#all?. Подтверждаю свою находку перезапуском ruby-prof callstack. | ||
| - Вместо того чтобы в каждой итерации проверять браузер на уникальность(uniqueBrowsers.all?), решил использовать Set, |
| - Защитил изменения обновлением перформенс теста. | ||
|
|
||
| ### Ваша находка №4 | ||
| - Для поиска главной точки роста решил использовать stackprof speedscope. Оценил удобство исользования и количество доступной информации. |
There was a problem hiding this comment.
👍 stackprof + speedscope = one love
| - Для поиска главной точки роста решил использовать stackprof speedscope. Оценил удобство исользования и количество доступной информации. | ||
| Определил что главная точка роста на данный момент Object#collect_stats_from_users(41%). | ||
| - В первую очередь вынес в отдельнвую перемменную user_stats = report['usersStats']. | ||
| Далее убрал ненужную тут конкатенацию "#{user.attributes['first_name']} #{user.attributes['last_name']}" |
There was a problem hiding this comment.
много изменений в одну итерацию == не понятно что сработало
| - С помощью callstack отчета отмечаю большую долю выполнения на <Class::Date>#parse | ||
| - Отмечаю что Date.parse тут необязателен, использую { 'dates' => user.sessions.map { |s| s['date'] }.sort.reverse } | ||
| - Бенчмарк показывает 19.3с на большом файле. Бюджет выполнен, решаю остановить оптимизацию. | ||
| - Избавился от точки роста в <Class::Date>#parse |
There was a problem hiding this comment.
да-да, это пасхалочка одна из моих любимых
| Для защиты от потери достигнутого прогресса при дальнейших изменениях программы *о performance-тестах, которые вы написали* | ||
| Для защиты от потери достигнутого прогресса при дальнейших изменениях программы написал перформанс тест который запускает | ||
| программу 2 раза и проверяет время выполнения на прокинутом в него файле за определнное количество времени. Тест обновлял | ||
| по мере оптимизации, увеличивая количество строк и задавая соответствующее время выполнения. |
No description provided.