Skip to content

Commit 64310f0

Browse files
committed
Make DBs run on ramdisk and optimize rspec parallelism
Since in a dev scenario we dont care about data loss we can speed up the tests majorly by running the DBs on a ramdisk. Also since the DB consumes CPU during the test its not good to start rspec executes equal to the number of CPU cores since the sume of load excedes that by a lot. So we leave 20% spare for the DB to have less CPU preemtive scheduling and all in all finish the rspecs faster. An environment variable was introduced PARALLEL_TEST_PROCESSORS_MULTIPLE that can be set to any floating point value and multiplies the CPU core count times PARALLEL_TEST_PROCESSORS_MULTIPLE. It defaults to 0.8 and rounds the CPU count up to the next integer so it cannot be less than 1 ever. Apply DB performance optimizations also for github actions
1 parent 40ddd8d commit 64310f0

File tree

7 files changed

+98
-22
lines changed

7 files changed

+98
-22
lines changed

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"nginx"
2121
],
2222
"workspaceFolder": "/workspace",
23-
"onCreateCommand": "bash .devcontainer/scripts/codespaces_start.sh",
23+
"onCreateCommand": "bash .devcontainer/scripts/startup.sh",
2424
"customizations": {
2525
// Configure properties specific to VS Code.
2626
"vscode": {

.devcontainer/scripts/codespaces_start.sh renamed to .devcontainer/scripts/startup.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ setupPostgres () {
1919
echo "Postgres is up."
2020

2121
# Parallel Test DBs
22+
export PARALLEL_TEST_PROCESSORS=`ruby -e 'require "etc"; puts (Etc.nprocessors * (ENV["PARALLEL_TEST_PROCESSORS_MULTIPLE"] || 0.8).to_f).ceil'`
2223
DB="postgres" POSTGRES_CONNECTION_PREFIX="postgres://postgres:supersecret@localhost:5432" bundle exec rake db:pick db:parallel:recreate
2324
# Sequential Test DBs
2425
export PGPASSWORD=supersecret
@@ -37,6 +38,7 @@ setupMariadb () {
3738
echo "MySQL is up."
3839

3940
# Parallel Test DBs
41+
export PARALLEL_TEST_PROCESSORS=`ruby -e 'require "etc"; puts (Etc.nprocessors * (ENV["PARALLEL_TEST_PROCESSORS_MULTIPLE"] || 0.8).to_f).ceil'`
4042
DB="mysql" MYSQL_CONNECTION_PREFIX="mysql2://root:[email protected]:3306" bundle exec rake db:pick db:parallel:recreate
4143
# Sequential Test DBs
4244
mysql -h 127.0.0.1 -u root -psupersecret -e "CREATE DATABASE IF NOT EXISTS cc_test; CREATE DATABASE IF NOT EXISTS diego; CREATE DATABASE IF NOT EXISTS locket;"
@@ -54,9 +56,6 @@ POSTGRES_PID=$!
5456
setupMariadb &
5557
MARIADB_PID=$!
5658

57-
wait $POSTGRES_PID
58-
wait $MARIADB_PID
59-
6059
# CC config
6160
mkdir -p tmp
6261
cp -a config/cloud_controller.yml tmp/cloud_controller.yml
@@ -120,4 +119,5 @@ yq -i e '.diego.bbs.ca_file="spec/fixtures/certs/bbs_ca.crt"' tmp/cloud_controll
120119

121120
yq -i e '.packages.max_package_size=2147483648' tmp/cloud_controller.yml
122121

123-
# Exit if any error happened
122+
wait $POSTGRES_PID
123+
wait $MARIADB_PID

.github/workflows/unit_tests.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,24 @@ jobs:
5454
--health-interval 10s
5555
--health-timeout 5s
5656
--health-retries 5
57+
--tmpfs /var/lib/postgresql/data
58+
--shm-size=256m
5759
ports:
5860
- 5432:5432
5961
steps:
6062
- uses: hmarr/debug-action@v3
6163
- uses: actions/checkout@v4
6264
- uses: ./.github/workflows/composite/setup
65+
- name: Configure PostgreSQL for performance
66+
run: |
67+
sudo apt-get update && sudo apt-get install -y postgresql-client
68+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET fsync = off;"
69+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET synchronous_commit = off;"
70+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET full_page_writes = off;"
71+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET checkpoint_completion_target = 0.9;"
72+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET wal_buffers = '16MB';"
73+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET shared_buffers = '256MB';"
74+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "SELECT pg_reload_conf();"
6375
- name: Run tests
6476
run: DB=postgres POSTGRES_CONNECTION_PREFIX="postgres://postgres:rootpassword@localhost:5432" bundle exec rake spec
6577
- uses: ravsamhq/notify-slack-action@v2
@@ -83,13 +95,24 @@ jobs:
8395
env:
8496
MYSQL_DATABASE: cc_test
8597
MYSQL_ROOT_PASSWORD: password
86-
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
98+
options: >-
99+
--health-cmd="mysqladmin ping"
100+
--health-interval=10s
101+
--health-timeout=5s
102+
--health-retries=3
103+
--tmpfs /var/lib/mysql
104+
--tmpfs /tmp
87105
ports:
88106
- 3306:3306
89107
steps:
90108
- uses: hmarr/debug-action@v3
91109
- uses: actions/checkout@v4
92110
- uses: ./.github/workflows/composite/setup
111+
- name: Configure MySQL for performance
112+
run: |
113+
sudo apt-get update && sudo apt-get install -y mysql-client
114+
mysql -h 127.0.0.1 -u root -ppassword -e "SET GLOBAL innodb_flush_log_at_trx_commit = 0;"
115+
mysql -h 127.0.0.1 -u root -ppassword -e "SET GLOBAL innodb_buffer_pool_size = 268435456;"
93116
- name: Run tests
94117
run: DB=mysql MYSQL_CONNECTION_PREFIX="mysql2://root:[email protected]:3306" bundle exec rake spec
95118
- uses: ravsamhq/notify-slack-action@v2
@@ -98,4 +121,4 @@ jobs:
98121
status: ${{ job.status }}
99122
notify_when: 'failure' # default is 'success,failure,warnings'
100123
env:
101-
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required
124+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # required

.github/workflows/unit_tests_backwards_compatibility.yml

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ concurrency:
44
cancel-in-progress: true
55
on:
66
workflow_dispatch:
7-
description: "This action tests backwards compatibility when db migrations are introduced. It tests database schema at new code(old_cc_ref) with unittests running old code(new_cc_ref) "
87
inputs:
98
old_cc_ref:
109
description: 'Old Version of CC_NG that the backwards compatibility should be checked against'
@@ -44,6 +43,8 @@ jobs:
4443
--health-interval 10s
4544
--health-timeout 5s
4645
--health-retries 5
46+
--tmpfs /var/lib/postgresql/data
47+
--shm-size=256m
4748
ports:
4849
- 5432:5432
4950
steps:
@@ -63,6 +64,16 @@ jobs:
6364
)}}
6465
- name: Setup Environment
6566
uses: ./.github/workflows/composite/setup
67+
- name: Configure PostgreSQL for performance
68+
run: |
69+
sudo apt-get update && sudo apt-get install -y postgresql-client
70+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET fsync = off;"
71+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET synchronous_commit = off;"
72+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET full_page_writes = off;"
73+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET checkpoint_completion_target = 0.9;"
74+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET wal_buffers = '16MB';"
75+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "ALTER SYSTEM SET shared_buffers = '256MB';"
76+
PGPASSWORD=rootpassword psql -h localhost -U postgres -c "SELECT pg_reload_conf();"
6677
- name: Migrate Database
6778
run: DB=postgres POSTGRES_CONNECTION_PREFIX="postgres://postgres:rootpassword@localhost:5432" bundle exec rake db:parallel:recreate db:parallel:migrate
6879
- name: Checkout code to run the unit tests with
@@ -92,7 +103,13 @@ jobs:
92103
env:
93104
MYSQL_DATABASE: cc_test
94105
MYSQL_ROOT_PASSWORD: password
95-
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
106+
options: >-
107+
--health-cmd="mysqladmin ping"
108+
--health-interval=10s
109+
--health-timeout=5s
110+
--health-retries=3
111+
--tmpfs /var/lib/mysql
112+
--tmpfs /tmp
96113
ports:
97114
- 3306:3306
98115
steps:
@@ -112,6 +129,11 @@ jobs:
112129
)}}
113130
- name: Setup Environment
114131
uses: ./.github/workflows/composite/setup
132+
- name: Configure MySQL for performance
133+
run: |
134+
sudo apt-get update && sudo apt-get install -y mysql-client
135+
mysql -h 127.0.0.1 -u root -ppassword -e "SET GLOBAL innodb_flush_log_at_trx_commit = 0;"
136+
mysql -h 127.0.0.1 -u root -ppassword -e "SET GLOBAL innodb_buffer_pool_size = 268435456;"
115137
- name: Migrate Database
116138
run: DB=mysql MYSQL_CONNECTION_PREFIX="mysql2://root:[email protected]:3306" bundle exec rake db:parallel:recreate db:parallel:migrate
117139
- name: Checkout code to run the unit tests with
@@ -125,4 +147,4 @@ jobs:
125147
- name: Setup Environment
126148
uses: ./.github/workflows/composite/setup
127149
- name: Run tests
128-
run: DB=mysql MYSQL_CONNECTION_PREFIX="mysql2://root:[email protected]:3306" bundle exec rake spec:without_migrate
150+
run: DB=mysql MYSQL_CONNECTION_PREFIX="mysql2://root:[email protected]:3306" bundle exec rake spec:without_migrate

devenv.sh

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ help_command() {
1818

1919
# Create a clean development environment
2020
create_command(){
21-
docker-compose -p "" down
21+
docker compose -p "" down
2222
docker buildx bake -f docker-compose.yml &
23-
docker-compose -p "" pull &
23+
docker compose -p "" pull &
2424
wait $(jobs -p)
25-
docker-compose -p "" up -d --build
26-
./.devcontainer/scripts/setupDevelopmentEnvironment.sh
25+
docker compose -p "" up -d --build
26+
./.devcontainer/scripts/startup.sh
2727
}
2828

2929
# Start containers
3030
start_command(){
31-
docker-compose -p "" start
31+
docker compose -p "" start
3232
}
3333

3434
# Stop containers
3535
stop_command(){
36-
docker-compose -p "" stop
36+
docker compose -p "" stop
3737
}
3838

3939
# Remove containers
4040
destroy_command(){
41-
docker-compose -p "" down
41+
docker compose -p "" down
4242
}
4343

4444
# Call Setup IDEs Script
@@ -72,7 +72,7 @@ fi
7272
# Check Prerequisites
7373
export should_exit=0
7474
# Check Path Exists
75-
for p in docker docker-compose ruby bundle mysql psql yq; do
75+
for p in docker ruby bundle mysql psql yq; do
7676
if ! command -v "${p}" >/dev/null 2>&1; then
7777
echo "Error: Dependency \"$p\" is not installed" && export should_exit=1
7878
fi

docker-compose.yml

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,26 @@ services:
77
environment:
88
POSTGRES_PASSWORD: supersecret
99
command:
10-
# logs every statement sent to the server. Slow, but helpful. Fills up disk Quickly !
1110
- "postgres"
12-
# - "-c"
13-
# - "log_statement=all"
11+
- "-c"
12+
- "fsync=off"
13+
- "-c"
14+
- "synchronous_commit=off"
15+
- "-c"
16+
- "full_page_writes=off"
17+
- "-c"
18+
- "log_statement=all"
19+
- "-c"
20+
- "checkpoint_segments=32"
21+
- "-c"
22+
- "checkpoint_completion_target=0.9"
23+
- "-c"
24+
- "wal_buffers=16MB"
25+
- "-c"
26+
- "shared_buffers=256MB"
27+
tmpfs:
28+
- /var/lib/postgresql/data
29+
shm_size: 256m
1430
ports:
1531
- "127.0.0.1:5432:5432"
1632
networks:
@@ -28,6 +44,18 @@ services:
2844
image: mysql:8.2
2945
environment:
3046
MYSQL_ROOT_PASSWORD: supersecret
47+
command:
48+
- "--innodb-flush-method=nosync"
49+
- "--innodb-flush-log-at-trx-commit=0"
50+
- "--innodb-doublewrite=0"
51+
- "--innodb-buffer-pool-size=256M"
52+
- "--innodb-log-buffer-size=16M"
53+
- "--innodb-log-file-size=64M"
54+
- "--skip-innodb-checksums"
55+
- "--skip-sync-frm"
56+
tmpfs:
57+
- /var/lib/mysql
58+
- /tmp
3159
ports:
3260
- "127.0.0.1:3306:3306"
3361
healthcheck:

lib/tasks/spec.rake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ desc 'Runs all specs'
22
task spec: 'spec:all'
33

44
namespace :spec do
5-
task all: ['db:pick', 'db:parallel:recreate'] do
5+
task all: ['db:pick'] do
6+
ENV['PARALLEL_TEST_PROCESSORS'] = (Etc.nprocessors * (ENV['PARALLEL_TEST_PROCESSORS_MULTIPLE'] || 0.8).to_f).ceil.to_s
7+
Rake::Task['db:parallel:recreate'].invoke
68
if ARGV[1]
79
run_specs(ARGV[1])
810
else
@@ -44,6 +46,7 @@ namespace :spec do
4446
def run_specs_parallel(path, env_vars='')
4547
command = <<~CMD
4648
#{env_vars} bundle exec parallel_rspec \
49+
-n `ruby -e 'require "etc"; puts (Etc.nprocessors * (ENV["PARALLEL_TEST_PROCESSORS_MULTIPLE"] || 0.8).to_f).ceil'` \
4750
--test-options '--order rand' \
4851
--single spec/integration/ \
4952
--single spec/acceptance/ \

0 commit comments

Comments
 (0)