Skip to content

Improve memory consumption of issuable APIs

Heinrich Lee Yu requested to merge 211373-improve-issues-list-api-memory into master

What does this MR do?

Sets replace_methods: false when batchloading issuable metadata. Explanation of this option is in: https://github.com/exAspArk/batch-loader#replacing-methods

For this particular case, the batch loader resolves Gitlab::IssuableMetadata::IssuableMeta objects which is a Struct. This results in __replace_with! being called on each of these.

[4] pry(main)> Gitlab::IssuableMetadata::IssuableMeta.new.methods.count
=> 198

This defines 198 methods per instance when we actually only call 5 of these methods. And we only call these methods only once so having them defined instead of relying on method_missing is not worth it. And for these API calls we'd have 20 to 100 instances depending on per_page values.

From local testing, disabling replace_methods even reduces cpu_s very slightly.

Sample logs before the change
{"time":"2021-05-12T06:22:48.629Z","severity":"INFO","duration_s":0.18625,"db_duration_s":0.0286,"view_duration_s":0.15765,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.115446,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.275191,"mem_objects":372737,"mem_bytes":21988696,"mem_mallocs":188096,"correlation_id":"01F5FKVZ04FVJNMSJE7BJA9T1V","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:22:49.445Z","severity":"INFO","duration_s":0.18799,"db_duration_s":0.02884,"view_duration_s":0.15915,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.119122,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.281203,"mem_objects":372763,"mem_bytes":21995864,"mem_mallocs":188105,"correlation_id":"01F5FKVZSF43EMPW5CMRZTAKZ8","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:22:50.309Z","severity":"INFO","duration_s":0.18767,"db_duration_s":0.02907,"view_duration_s":0.1586,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.132683,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.294494,"mem_objects":372770,"mem_bytes":22135288,"mem_mallocs":190615,"correlation_id":"01F5FKW0M21MJSPS2Z8V5V2MHQ","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:22:51.019Z","severity":"INFO","duration_s":0.19539,"db_duration_s":0.02928,"view_duration_s":0.16611,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.118343,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.288916,"mem_objects":372747,"mem_bytes":21995864,"mem_mallocs":188105,"correlation_id":"01F5FKW1ADQNCDZ2HZXSJHHMGZ","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:22:51.735Z","severity":"INFO","duration_s":0.19222,"db_duration_s":0.02829,"view_duration_s":0.16393,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.117654,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.284387,"mem_objects":372763,"mem_bytes":21995888,"mem_mallocs":188105,"correlation_id":"01F5FKW20X8G2W56DAFMZFVM95","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:22:52.442Z","severity":"INFO","duration_s":0.18587,"db_duration_s":0.02855,"view_duration_s":0.15732,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.125344,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.276808,"mem_objects":372772,"mem_bytes":21995864,"mem_mallocs":188105,"correlation_id":"01F5FKW2Q06GBBG0E8AP4HBKKV","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
Sample logs after the change
{"time":"2021-05-12T06:27:37.031Z","severity":"INFO","duration_s":0.1684,"db_duration_s":0.02812,"view_duration_s":0.14028,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.129815,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.27261,"mem_objects":293662,"mem_bytes":13248280,"mem_mallocs":107112,"correlation_id":"01F5FM4RMTAXXC8WRHJ3B4V3WT","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:27:37.858Z","severity":"INFO","duration_s":0.18477,"db_duration_s":0.02964,"view_duration_s":0.15513,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.119745,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.277354,"mem_objects":293667,"mem_bytes":13306360,"mem_mallocs":107892,"correlation_id":"01F5FM4SEE9C9PGTCK3S94K3Y5","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:27:38.676Z","severity":"INFO","duration_s":0.16984,"db_duration_s":0.02886,"view_duration_s":0.14098,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.119228,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.262974,"mem_objects":293666,"mem_bytes":13159224,"mem_mallocs":105907,"correlation_id":"01F5FM4T8GZ47A58143SX0FYNP","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:27:39.560Z","severity":"INFO","duration_s":0.18291,"db_duration_s":0.02952,"view_duration_s":0.15339,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.124057,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.280885,"mem_objects":293670,"mem_bytes":13282696,"mem_mallocs":107512,"correlation_id":"01F5FM4V3HDVNK81YNAZNW4SZ9","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:27:40.364Z","severity":"INFO","duration_s":0.17219,"db_duration_s":0.02941,"view_duration_s":0.14278,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.135933,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.281485,"mem_objects":293664,"mem_bytes":13248488,"mem_mallocs":108172,"correlation_id":"01F5FM4VWMWVD7RK2CEZ01W87P","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:27:41.139Z","severity":"INFO","duration_s":0.1687,"db_duration_s":0.02784,"view_duration_s":0.14086,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.116833,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.260638,"mem_objects":293662,"mem_bytes":13157784,"mem_mallocs":105904,"correlation_id":"01F5FM4WNH48PEDAMG3R2Y2B6B","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}
{"time":"2021-05-12T06:27:43.367Z","severity":"INFO","duration_s":0.17228,"db_duration_s":0.02873,"view_duration_s":0.14355,"status":200,"method":"GET","path":"/api/v4/projects/1/issues","params":[],"host":"engwan-dev","remote_ip":"192.168.88.241","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0","route":"/api/:version/projects/:id/issues","user_id":1,"username":"root","queue_duration_s":0.11832,"db_count":27,"db_write_count":0,"db_cached_count":5,"cpu_s":0.264453,"mem_objects":293662,"mem_bytes":13165016,"mem_mallocs":105907,"correlation_id":"01F5FM4YV1RDSR7F642RXH5ZPH","meta.user":"root","meta.project":"gitlab-org/gitlab-test","meta.root_namespace":"gitlab-org","meta.caller_id":"GET /api/:version/projects/:id/issues","meta.remote_ip":"172.18.0.1","meta.feature_category":"issue_tracking","meta.client_id":"user/1"}

From the logs we can see that mem_objects, mem_bytes, and mem_mallocs go down by a sizeable amount.

I am hoping this can help with #211373 (closed) because I see a lot of GC cycles during the performance test for this endpoint.

I'm struggling to find a lower hanging fruit to improve performance of this endpoint because it's already fast in staging (~300ms) but not in reference environments (~1s). https://staging.gitlab.com/api/v4/projects/gpt%2Flarge_projects%2Fgitlabhq1/issues is the URL being tested.

Screenshots (strongly suggested)

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

Does this MR contain changes to processing or storing of credentials or tokens, authorization and authentication methods or other items described in the security review guidelines? If not, then delete this Security section.

  • 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

Related to #211373 (closed)

Edited by Heinrich Lee Yu

Merge request reports