Fix slow group loading on forking page
requested to merge 235912-fork-interface-with-prevent-forking-outside-a-group-is-extremely-slow into master
What does this MR do?
After introducing separate group loading on forking page, there was a really high page load times observed for large sets of data.
On local environment for ~1000 groups here are apache bench results:
ab -n 10 -C '_gitlab_session_7b75811b6f331df2ddd5b02eab038350b74456e89a857d26320864e9914e2b3b=c84888787b60da75e535871996c77555' 'http://127.0.0.1:3000/root/apitest/-/forks/new.json'
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /root/apitest/-/forks/new.json
Document Length: 441241 bytes
Concurrency Level: 1
Time taken for tests: 158.401 seconds
Complete requests: 10
Failed requests: 0
Total transferred: 4421359 bytes
HTML transferred: 4412410 bytes
Requests per second: 0.06 [#/sec] (mean)
Time per request: 15840.073 [ms] (mean)
Time per request: 15840.073 [ms] (mean, across all concurrent requests)
Transfer rate: 27.26 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.1 1 1
Processing: 14391 15840 1513.7 15453 19164
Waiting: 14389 15837 1513.6 15450 19160
Total: 14392 15840 1513.8 15454 19165
Percentage of the requests served within a certain time (ms)
50% 15454
66% 15584
75% 15598
80% 17959
90% 19165
95% 19165
98% 19165
99% 19165
100% 19165 (longest request)
What I did:
- I created easy-accesible hash with memberships that is used in serializer instead of querying database for each group.
- I added preloading of
routes
- I added preloading for
deletion_schedule
Apache bench results after changes:
ab -n 4 -C '_gitlab_session_7b75811b6f331df2ddd5b02eab038350b74456e89a857d26320864e9914e2b3b=c84888787b60da75e535871996c77555' 'http://127.0.0.1:3000/root/apitest/-/forks/new.json'
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /root/apitest/-/forks/new.json
Document Length: 441241 bytes
Concurrency Level: 1
Time taken for tests: 14.226 seconds
Complete requests: 4
Failed requests: 0
Total transferred: 1768540 bytes
HTML transferred: 1764964 bytes
Requests per second: 0.28 [#/sec] (mean)
Time per request: 3556.573 [ms] (mean)
Time per request: 3556.573 [ms] (mean, across all concurrent requests)
Transfer rate: 121.40 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.0 1 1
Processing: 3010 3556 904.9 3155 4910
Waiting: 3006 3553 904.9 3152 4906
Total: 3010 3557 904.9 3156 4910
Percentage of the requests served within a certain time (ms)
50% 3156
66% 3156
75% 4910
80% 4910
90% 4910
95% 4910
98% 4910
99% 4910
100% 4910 (longest request)
I know for seconds is not super fast, but it's for huge set of data and it's on local machine.
Screenshots
Before changes, what I observed in logs: this part was repeated for every group:
[1m[36mRoute Load (0.1ms)[0m [1m[34mSELECT "routes".* FROM "routes" WHERE "routes"."source_id" = $1 AND "routes"."source_type" = $2 LIMIT $3[0m [["source_id", 1011], ["source_type", "Namespace"], ["LIMIT", 1]]
↳ app/models/concerns/routable.rb:70:in `full_name'
[1m[36mMember Load (0.2ms)[0m [1m[34mSELECT "members".* FROM "members" WHERE "members"."user_id" = $1 AND "members"."source_type" = $2 AND "members"."source_id" = $3 LIMIT $4[0m [["user_id", 2], ["source_type", "Namespace"], ["source_id", 1011], ["LIMIT", 1]]
↳ app/serializers/fork_namespace_entity.rb:43:in `membership'
[1m[36mGroupDeletionSchedule Load (0.3ms)[0m [1m[34mSELECT "group_deletion_schedules".* FROM "group_deletion_schedules" WHERE "group_deletion_schedules"."group_id" = $1 LIMIT $2[0m [["group_id", 1011], ["LIMIT", 1]]
↳ ee/app/models/ee/group.rb:48:in `marked_for_deletion_on'
now:
SELECT "group_deletion_schedules".* FROM "group_deletion_schedules" WHERE "group_deletion_schedules"."group_id" IN ...
and
SELECT "routes".* FROM "routes" WHERE "routes"."source_type" = $1 AND "routes"."source_id" IN ...
and
SELECT "members".* FROM "members" WHERE "members"."user_id" = ...
Does this MR meet the acceptance criteria?
Conformity
-
Changelog entry -
Documentation (if required) -
Code review guidelines -
Merge request performance guidelines -
Style guides -
Database guides -
Separation of EE specific content
Availability and Testing
-
Review and add/update tests for this feature/bug. Consider all test levels. See the Test Planning Process. -
Tested in all supported browsers -
Informed Infrastructure department of a default or new setting change, if applicable per definition of done
Security
If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:
-
Label as security and @ mention @gitlab-com/gl-security/appsec
-
The MR includes necessary changes to maintain consistency between UI, API, email, or other methods -
Security reports checked/validated by a reviewer from the AppSec team
Closes #235912 (closed)
Edited by Gosia Ksionek