From 1da88d4adebac9970654434996442431ce75915b Mon Sep 17 00:00:00 2001 From: Kirill Usanov Date: Mon, 29 Nov 2021 00:39:55 +0300 Subject: [PATCH 1/3] Case study --- .gitignore | 8 ++ case-study.md | 122 +++++++++++++++++++++++++++++++ reports/factory_flame_after.jpg | Bin 0 -> 55109 bytes reports/factory_flame_before.jpg | Bin 0 -> 51862 bytes reports/influx_graph.jpg | Bin 0 -> 57342 bytes 5 files changed, 130 insertions(+) create mode 100644 .gitignore create mode 100644 case-study.md create mode 100644 reports/factory_flame_after.jpg create mode 100644 reports/factory_flame_before.jpg create mode 100644 reports/influx_graph.jpg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2de380 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +#Jetbrains Tools +.idea/ diff --git a/case-study.md b/case-study.md new file mode 100644 index 0000000..1a0a9b6 --- /dev/null +++ b/case-study.md @@ -0,0 +1,122 @@ +# Подготовка + +Подключил `bootsnap`. +Попытался отключить от проекта `DatabaseCleaner`, но тесты падают с непонятной ошибкой, потому решил пока что его не трогать, чтобы не тратить время. + +# Профилирование фабрик + +`FPROF=1 rspec` + +``` +[TEST PROF INFO] Factories usage + + Total: 1336 + Total top-level: 744 + Total time: 00:06.663 (out of 00:13.090) + Total uniq factories: 15 + + total top-level total time time per call top-level time name + + 542 15 1.5699s 0.0029s 0.0478s office + 527 491 4.3891s 0.0083s 4.0996s user + 66 59 0.2743s 0.0042s 0.2505s oauth_application + 34 34 0.1246s 0.0037s 0.1246s users_oauth_application + 29 29 1.4607s 0.0504s 1.4607s user_account + 29 15 0.0944s 0.0033s 0.0455s team + 29 21 0.0690s 0.0024s 0.0453s host + 28 28 0.0709s 0.0025s 0.0709s vpn_server + 24 24 0.2539s 0.0106s 0.2539s vpn_key + 12 12 0.1038s 0.0087s 0.1038s mailbox + 10 10 0.1196s 0.0120s 0.1196s api_log + 2 2 0.0190s 0.0095s 0.0190s access_token + 2 2 0.0160s 0.0080s 0.0160s access_grant + 1 1 0.0035s 0.0035s 0.0035s users_host + 1 1 0.0024s 0.0024s 0.0024s users_vpn_server +``` + +В глаза сразу бросается, что в топе висит `office` - быть на первом месте он точно не должен. Посмотрев на фабрики, становится ясно, что он каскадно создается при создании записи `user`. + +# RSpecDissect + +`RD_PROF=1 rspec` + +``` +TEST PROF INFO] RSpecDissect report + +Total time: 00:15.160 + +Total `let` time: 00:09.162 +Total `before(:each)` time: 00:06.904 + +Top 5 slowest suites (by `let` time): + +Api::V2::AccountsController (./spec/controllers/api-v2/accounts_controller_spec.rb:4) – 00:02.078 of 00:02.640 (71) + ↳ record1 – 92 + ↳ record2 – 72 + ↳ record3 – 72 +``` + +Как видно, в топе находится api-v2 endpoint. Покопаем глубже под него. + +# stackprof flamegraph +`TEST_STACK_PROF=1 TEST_STACK_PROF_FORMAT=json rspec spec/controllers/api-v2/` + +Ничего примечательного не нашел, в топе вызовов все стандартно. + +# ruby-prof calltree +`TEST_RUBY_PROF=call_tree rspec spec/controllers/api-v2/` + +Аналогично, ничего примечательного. + +# Flamegraph для фабрик + +`FPROF=flamegraph rspec spec/controllers/api-v2/` + +![Screenshot](reports/factory_flame_before.jpg?raw=true) + +Вот тут уже становится жарко - присутствует очень большое количество созданных фабрикой записей в БД, с каскадностью. Нужно исправлять. + +При этом, `test-prof` пишет, что все в норме. + +`[TEST PROF INFO] FactoryDoctor says: "Looks good to me!"` + +# Оптимизация api/v2 + +Воспользуемся `before_all` для того, чтобы не создавать множество одинаковых записей. + +![Screenshot](reports/factory_flame_after.jpg?raw=true) + +После оптимизации вместо ~350 записей создается лишь 19. Этот блок тестов пропал из всех отчетов, при этом общее время выполнения уменьшилось на 33% (15 -> 10 секунд), для `let` и `before(:each)` - примерно на 50%. + +``` +[TEST PROF INFO] RSpecDissect report + +Total time: 00:10.049 + +Total `let` time: 00:05.372 +Total `before(:each)` time: 00:03.610 +``` + +# Параллельные тесты + +Подключил `gem 'parallel_test'` + +Попробую найти оптимальное количество параллельных процессов. + +Для 1: 10.5 (+ 2.5) с. + +Для 2: 8 с. + +Для 3: 7 с. + +Для 4: 6 c. + +Ввыглядит оптимальным использовать 3 процесса, далее прирост получается совсем незначительным. + +# Вывод + +![Screenshot](reports/influx_graph.jpg?raw=true) + +Достаточно быстро получилось ускорить test suite в 2 раза. +Очень хороший результат для кажущегося до этого неплохого test suite'а. + diff --git a/reports/factory_flame_after.jpg b/reports/factory_flame_after.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8f01efe5bdf4a4a4f690971092a9627d8613f2b GIT binary patch literal 55109 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 Gmj3|=Gj|>U literal 0 HcmV?d00001 diff --git a/reports/factory_flame_before.jpg b/reports/factory_flame_before.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1289d1c00eb0a4569f683ae0b4392d8a534f2403 GIT binary patch literal 51862 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 literal 0 HcmV?d00001 diff --git a/reports/influx_graph.jpg b/reports/influx_graph.jpg new file mode 100644 index 0000000000000000000000000000000000000000..87e90d30c8b62f3d365feb36121d924c87fc2add GIT binary patch literal 57342 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�aZEABhULDNV6zi}d6^ki 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 Date: Mon, 29 Nov 2021 00:41:38 +0300 Subject: [PATCH 2/3] Case study fix --- case-study.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/case-study.md b/case-study.md index 1a0a9b6..1d1be62 100644 --- a/case-study.md +++ b/case-study.md @@ -1,7 +1,9 @@ # Подготовка Подключил `bootsnap`. -Попытался отключить от проекта `DatabaseCleaner`, но тесты падают с непонятной ошибкой, потому решил пока что его не трогать, чтобы не тратить время. +Попытался отключить от проекта `DatabaseCleaner`, но тесты падают с непонятной ошибкой, +потому решил пока что его не трогать, чтобы не тратить время. +Практика показывает, что какого-то ощутимого падения производительности test suite'а он не вызывает. # Профилирование фабрик @@ -34,7 +36,8 @@ 1 1 0.0024s 0.0024s 0.0024s users_vpn_server ``` -В глаза сразу бросается, что в топе висит `office` - быть на первом месте он точно не должен. Посмотрев на фабрики, становится ясно, что он каскадно создается при создании записи `user`. +В глаза сразу бросается, что в топе висит `office` - быть на первом месте он точно не должен. +Посмотрев на фабрики, становится ясно, что он каскадно создается при создании записи `user`. # RSpecDissect @@ -68,15 +71,16 @@ Api::V2::AccountsController (./spec/controllers/api-v2/accounts_controller_spec. Аналогично, ничего примечательного. -# Flamegraph для фабрик +# Factory Flamegraph `FPROF=flamegraph rspec spec/controllers/api-v2/` ![Screenshot](reports/factory_flame_before.jpg?raw=true) -Вот тут уже становится жарко - присутствует очень большое количество созданных фабрикой записей в БД, с каскадностью. Нужно исправлять. +Вот тут уже становится жарко - присутствует очень большое количество созданных фабрикой записей в БД, с каскадностью. +Нужно исправлять. -При этом, `test-prof` пишет, что все в норме. +При этом, `test-prof` пишет, что все в норме. Но это точно не так и следует исправить. `[TEST PROF INFO] FactoryDoctor says: "Looks good to me!"` @@ -86,7 +90,9 @@ Api::V2::AccountsController (./spec/controllers/api-v2/accounts_controller_spec. ![Screenshot](reports/factory_flame_after.jpg?raw=true) -После оптимизации вместо ~350 записей создается лишь 19. Этот блок тестов пропал из всех отчетов, при этом общее время выполнения уменьшилось на 33% (15 -> 10 секунд), для `let` и `before(:each)` - примерно на 50%. +После оптимизации вместо ~350 записей создается лишь 19. +Этот блок тестов пропал из всех отчетов, при этом общее время выполнения уменьшилось на 33% (15 -> 10 секунд), +для `let` и `before(:each)` - примерно на 50%. ``` [TEST PROF INFO] RSpecDissect report @@ -111,7 +117,7 @@ Total `before(:each)` time: 00:03.610 Для 4: 6 c. -Ввыглядит оптимальным использовать 3 процесса, далее прирост получается совсем незначительным. +Выглядит оптимальным использовать 3 процесса, далее прирост получается совсем незначительным. # Вывод @@ -119,4 +125,3 @@ Total `before(:each)` time: 00:03.610 Достаточно быстро получилось ускорить test suite в 2 раза. Очень хороший результат для кажущегося до этого неплохого test suite'а. - From daa9b9114dc587290b7921f23603fc1d4f869f53 Mon Sep 17 00:00:00 2001 From: Kirill Usanov Date: Mon, 29 Nov 2021 01:31:51 +0300 Subject: [PATCH 3/3] Updated case-study --- case-study.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/case-study.md b/case-study.md index 1d1be62..9e62b7c 100644 --- a/case-study.md +++ b/case-study.md @@ -3,8 +3,22 @@ Подключил `bootsnap`. Попытался отключить от проекта `DatabaseCleaner`, но тесты падают с непонятной ошибкой, потому решил пока что его не трогать, чтобы не тратить время. + +``` +Failure/Error: require File.expand_path('../../config/environment', __FILE__) + +FrozenError: + can't modify frozen Array: [ActionDispatch::HostAuthorization, ...] +``` + Практика показывает, что какого-то ощутимого падения производительности test suite'а он не вызывает. +UPD. Все-таки продебажил запуск test environment и понял, что проблема не в `DatabaseCleaner`, +а в ленивой загрузке классов `Doorkeeper`, которая выполнялась лишь после загрузки фабрик `factory_bot`, +что `DatabaseCleaner` каким-то чудным образом решал. Не такой уж он и бесполезный :) + +Но, как и ожидалось, никакого прироста производительности. + # Профилирование фабрик `FPROF=1 rspec`