2 min read

Tuning Gitlab Performance

Tuning Gitlab Performance

Introduction

GitLab requires a significant amount of memory when running with all features enabled. There are use-cases such as running GitLab on smaller installations where not all functionality is required. Examples include:

  • Running GitLab for personal use or very small teams.
  • Using a small instance on a cloud provider for cost savings.
  • Using resource-constrained devices like the Raspberry PI.

With some adjustments, GitLab can run comfortably on much lower specifications than described in minimum requirements or the reference architectures.

The following sections contain advice that will allow GitLab to run in environments that do not meet the minimum requirements. While most GitLab parts should be functional with these settings in place, you may experience unexpected degradation of both product functionality and performance.

Optimize Sidekiq

Sidekiq is a background processing daemon. When configured with GitLab by default it runs with a high concurrency mode of 50. This does impact how much memory it can allocate at a given time. It is advised to configure it to use a significantly smaller value of 5 or 10 (preferred).

 sidekiq['max_concurrency'] = 10
 sidekiq['min_concurrency'] = nil

Optimize Puma

GitLab by default runs with a configuration that is designed to handle many concurrent connections. For small installations, which do not require high throughput, consider disabling Puma Clustered mode. As the result, only a single Puma process would serve the application.

 puma['worker_processes'] = 1

Configure how GitLab handles memory

GitLab consists of many components (written in Ruby and Go), with GitLab Rails being the biggest one and consuming the most of memory.

GitLab Rails uses jemalloc as a memory allocator. jemalloc preallocates memory in bigger chunks that are also being held for longer periods in order to improve performance. At the expense of some performance loss, you can configure GitLab to free memory right after it is no longer needed instead of holding it for a longer periods.

 gitlab_rails['env'] = {
    'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
 }

Disable monitoring

GitLab enables all services by default to provide a complete DevOps solution without any additional configuration. Some of the default services, like monitoring, are not essential for GitLab to function and can be disabled to save memory.

 prometheus['enable'] = false
 prometheus_monitoring['enable'] = false

Full Code

Here's the Full Code

Before

# sidekiq['max_concurrency'] = 20
# sidekiq['min_concurrency'] = nil
# puma['worker_processes'] = 2
# gitlab_rails['env'] = {
#    "SKIP" => "db,uploads,repositories,builds,artifacts,lfs,registry,pages"
# }
# prometheus['enable'] = true
# prometheus_monitoring['enable'] = true

After

 sidekiq['max_concurrency'] = 10
 sidekiq['min_concurrency'] = nil
 puma['worker_processes'] = 1
 gitlab_rails['env'] = {
    'MALLOC_CONF' => 'dirty_decay_ms:1000,muzzy_decay_ms:1000'
 }
 prometheus['enable'] = false
 prometheus_monitoring['enable'] = false

Reconfigure Gitlab

To Apply all those changes, we need to reconfigure & restart Gitlab.

gitlab-ctl reconfigure
gitlab-ctl restart

Reference

Running GitLab in a memory-constrained environment | GitLab
Documentation for GitLab Community Edition, GitLab Enterprise Edition, Omnibus GitLab, and GitLab Runner.