Conversation
| ### Ваша находка №4 | ||
| - MemoryProfiler указывает на строку с парсингом даты. Оптимизируем | ||
| - Метрика изменилась с 46 МБ до 35 МБ | ||
| - строка с датой занимала *13 МБ* и аллоцировала *171163 (!)* объекта. После оптимизации стала занимать *1 МБ с 9929 объектами*. Очень наглядная оптимизация :smirk: |
| ### Ваша находка №5 | ||
| - Дальнейшее профилирование указывает на split (это необходимо) и генерацию и накопление массивов с пользователями и сессиями. | ||
| - Поэтому решаем переписать программу на потоковый режим работы. В память будет загружаться информация о пользователе и его сессиях, считаться статистика, и записываться в файл. После чего в память будет загружаться следующий пользователь. | ||
| - Метрика показывает результат выполнения 21 МБ. Причём как на 10_000, так и на 3_250_940 строк (файл data_large.txt). Это означает, что мы вложились в бюджет (< 70 МБ). Ура! :smiley: |
There was a problem hiding this comment.
👍 и самое приятное, что так любой объём данных можно перелопатить
| - После оптимизации программы решил проверить как влияет фриз строк после оптимизации, и выяснил интересный момент - на 100 000 строках: | ||
| - 146 МБ - без фриза | ||
| - 139 МБ - с фризом | ||
| Получается, данная оптимизация не зависит от количества данных, а зависит от количества использования String в программе? |
There was a problem hiding this comment.
он же фризит только строковые литералы в коде; от данных не зависит
| Получается, данная оптимизация не зависит от количества данных, а зависит от количества использования String в программе? | ||
|
|
||
| ### Замер скорости | ||
| - После оптимизации по памяти провели тестирование на времени выполнения программы. С файлом data_large.txt оно составило - **всего лишь 22 секунды(!)** против 32 сек до оптимизации памяти. Возможно, разница больше, так как замеры выполнялись на разных конфигурациях VM |
There was a problem hiding this comment.
Да, чаще всего у всех получается в таком подходе результаты лучше чем в первом ДЗ
Такой интересный момент, что когда заходили только с точки зрения CPU вроде бы более прямо ориентировались на время выполнения; но работа с памятью и GC могут давать свои тормоза, которые мы можем не заметить при профилировании CPU. Хотя справедливости ради зачастую именно GC бывает на первых местах в отчётах профилировщиков CPU. Тогда можно задуматься о том, что надо как-то объектов поменьше аллоцировать постараться
| ## Результаты | ||
| - В результате проделанной оптимизации наконец удалось обработать файл с данными. Удалось улучшить метрику системы с 767 МБ до 29 МБ и уложиться в заданный бюджет < 70 MB. | ||
| - Приобрел практические навыки в оптимизации используемой памяти в работе приложений | ||
| - На практике выявил сильную взаимосвязь между оптимизацией CPU и памятью |
|
|
||
| report['uniqueBrowsersCount'] = uniqueBrowsers.count | ||
| File.foreach('data_large.txt') do |line| | ||
| line_type, *fields = line.chomp.split(',') |
There was a problem hiding this comment.
тут на самом деле есть вариант сэкономить на аллокациях - использовать split with block
или скажем идти по строке посимвольно и записывать подстроки в 4-5 заранее заготовленных строковых переменных (сколько там полей)
но это экономия на спичках уже в данном случае
memory_profilerruby-profв режимеFlat;ruby-profв режимеGraph;ruby-profв режимеCallStack;ruby-profв режимеCallTreec визуализацией вKCachegrind;stackprof;flamegraphс помощьюstackprofи визуализировать его вspeedscope.app;valgrind massif visualierи включить скриншот в описание вашегоPR;Не удалось корректно проанализировать с Valgrind - отказывается профилировать, искал различные пути решения и настройки, но не докопался. Вот что в логе: