Tes Performance Memcached
Seberapa signifikan Memcached dapat mengurangi beban server kamu?
Di tulisan sebelumnya, saya sudah menyampaikan beberapa hal mengenai Memcached dan bagaimana implementasi Memcached dapat (berpotensi) mengurangi biaya server kamu. Di tulisan kali ini, saya akan coba membuat perbandingan performance antara aplikasi website yang tidak menggunakan Memcached dengan yang menggunakan Memcached.
Skenario Tes
Skenario tes yang akan saya lakukan sebetulnya cukup sederhana. Tes tersebut merupakan A/B test yang akan membuat simulasi load test sederhana menggunakan tool ab dan wrk. Endpoint yang akan menjadi parameter load test hanya melakukan query SQL SELECT
sederhana, dimana query tersebut bertujuan untuk mengambil konfigurasi aplikasi yang disimpan di database. Skenario load test yang dilakukan adalah sebagai berikut:
Mengirim 1000 sequential request: 1000 request akan diproses 1 per 1 secara bergantian oleh server
Mengirim 1000 concurrent request: 1000 request akan diproses secara bersamaan oleh server
Skenario ini mungkin hanya simulasi yang sangat sederhana jika dibandingkan dengan skenario high traffic di dunia nyata. Namun setidaknya bisa memberi kita gambaran bagaimana dampak dari implementasi Memcached terhadap performance dari aplikasi kita.
Environment dan Alat Tes
Tes dilakukan dengan environment dan alat tes sebagai berikut:
Linux Mint 22, Intel Core i7-1255U 10 core/12 thread
nginx 1.24
PHP 8.3.9, Laravel 11.17.0
MS SQL Server 2022
memcached 1.6.24
ab 2.3
wrk 4.2.0
source code aplikasi yang digunakan untuk tes dapat diunduh disini
Berikut merupakan konfigurasi pool php-fpm
yang digunakan:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
Hasil Tes
Tanpa Memcached: 1000 sequential request
Menggunakan ab
ab -n 1000 http://test-memcached.test/load-test/no-cache
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking test-memcached.test (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.24.0
Server Hostname: test-memcached.test
Server Port: 80
Document Path: /load-test/no-cache
Document Length: 0 bytes
Concurrency Level: 1
Time taken for tests: 28.543 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1140000 bytes
HTML transferred: 0 bytes
Requests per second: 35.03 [#/sec] (mean)
Time per request: 28.543 [ms] (mean)
Time per request: 28.543 [ms] (mean, across all concurrent requests)
Transfer rate: 39.00 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 25 28 2.6 28 46
Waiting: 25 28 2.6 28 46
Total: 25 28 2.6 28 46
Percentage of the requests served within a certain time (ms)
50% 28
66% 29
75% 29
80% 29
90% 31
95% 33
98% 37
99% 41
100% 46 (longest request)
Menggunakan wrk
wrk -t1 -c1 -d30s http://test-memcached.test/load-test/no-cache --latency
Running 30s test @ http://test-memcached.test/load-test/no-cache
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 28.82ms 2.78ms 50.81ms 82.13%
Req/Sec 34.70 5.33 40.00 98.00%
Latency Distribution
50% 28.06ms
75% 29.73ms
90% 32.01ms
99% 41.65ms
1041 requests in 30.02s, 1.13MB read
Requests/sec: 34.67
Transfer/sec: 38.60KB
Dengan Memcached: 1000 sequential request
Menggunakan ab
ab -n 1000 http://test-memcached.test/load-test/cache
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking test-memcached.test (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.24.0
Server Hostname: test-memcached.test
Server Port: 80
Document Path: /load-test/cache
Document Length: 0 bytes
Concurrency Level: 1
Time taken for tests: 5.604 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1140000 bytes
HTML transferred: 0 bytes
Requests per second: 178.44 [#/sec] (mean)
Time per request: 5.604 [ms] (mean)
Time per request: 5.604 [ms] (mean, across all concurrent requests)
Transfer rate: 198.66 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 3 6 1.4 6 34
Waiting: 3 5 1.4 6 34
Total: 3 6 1.4 6 34
Percentage of the requests served within a certain time (ms)
50% 6
66% 6
75% 6
80% 6
90% 7
95% 8
98% 8
99% 9
100% 34 (longest request)
Menggunakan wrk
wrk -t1 -c1 -d6s http://test-memcached.test/load-test/cache --latency
Running 6s test @ http://test-memcached.test/load-test/cache
1 threads and 1 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.57ms 1.31ms 15.07ms 69.05%
Req/Sec 180.05 24.36 240.00 68.33%
Latency Distribution
50% 5.57ms
75% 6.07ms
90% 7.14ms
99% 9.56ms
1078 requests in 6.01s, 1.17MB read
Requests/sec: 179.46
Transfer/sec: 199.79KB
Tanpa Memcached: 1000 concurrent request
Menggunakan ab
ab -n 1000 -c 1000 http://test-memcached.test/load-test/no-cache
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking test-memcached.test (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.24.0
Server Hostname: test-memcached.test
Server Port: 80
Document Path: /load-test/no-cache
Document Length: 0 bytes
Concurrency Level: 1000
Time taken for tests: 28.368 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1140000 bytes
HTML transferred: 0 bytes
Requests per second: 35.25 [#/sec] (mean)
Time per request: 28368.105 [ms] (mean)
Time per request: 28.368 [ms] (mean, across all concurrent requests)
Transfer rate: 39.24 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 13 0.5 13 14
Processing: 49 14715 8161.0 14715 28306
Waiting: 35 14715 8161.0 14715 28306
Total: 49 14728 8161.0 14728 28320
Percentage of the requests served within a certain time (ms)
50% 14728
66% 19243
75% 21769
80% 23213
90% 26075
95% 27521
98% 28198
99% 28274
100% 28320 (longest request)
Menggunakan wrk
wrk -t12 -c1000 -d30s http://test-memcached.test/load-test/no-cache --latency
Running 30s test @ http://test-memcached.test/load-test/no-cache
12 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.29s 389.35ms 1.98s 58.82%
Req/Sec 10.14 9.05 60.00 69.31%
Latency Distribution
50% 1.27s
75% 1.60s
90% 1.85s
99% 1.98s
1039 requests in 30.10s, 1.13MB read
Socket errors: connect 0, read 0, write 0, timeout 988
Requests/sec: 34.52
Transfer/sec: 38.43KB
Dengan Memcached: 1000 concurrent request
Menggunakan ab
ab -n 1000 -c 1000 http://test-memcached.test/load-test/cache
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking test-memcached.test (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.24.0
Server Hostname: test-memcached.test
Server Port: 80
Document Path: /load-test/cache
Document Length: 0 bytes
Concurrency Level: 1000
Time taken for tests: 0.620 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1140000 bytes
HTML transferred: 0 bytes
Requests per second: 1612.64 [#/sec] (mean)
Time per request: 620.100 [ms] (mean)
Time per request: 0.620 [ms] (mean, across all concurrent requests)
Transfer rate: 1795.33 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 12 0.7 12 13
Processing: 15 288 160.8 287 558
Waiting: 14 288 160.8 287 558
Total: 28 300 160.2 300 569
Percentage of the requests served within a certain time (ms)
50% 300
66% 390
75% 440
80% 468
90% 523
95% 553
98% 566
99% 568
100% 569 (longest request)
Menggunakan wrk
wrk -t12 -c1000 -d1s http://test-memcached.test/load-test/cache --latency
Running 1s test @ http://test-memcached.test/load-test/cache
12 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 399.21ms 173.74ms 582.03ms 76.76%
Req/Sec 225.81 238.78 808.00 81.25%
Latency Distribution
50% 483.46ms
75% 549.28ms
90% 557.41ms
99% 569.83ms
1790 requests in 1.06s, 1.95MB read
Requests/sec: 1684.16
Transfer/sec: 1.83MB
Analisa Hasil
Saat menjalankan tes, selain terlihat perbedaan waktu respon dari aplikasi, saya juga melihat adanya perbedaan dalam penggunaan resource. Saat tidak menggunakan memcached, terlihat bahwa SQL Server paling banyak menggunakan CPU.
Ini menunjukkan bahwa setiap kali ada request, aplikasi langsung melakukan eksekusi query SQL pada engine SQL Server sehingga menyebabkan aplikasi lebih banyak menunggu respon dari SQL Server (bottleneck). Inilah yang menyebabkan mengapa pada skenario tanpa memcached, jumlah request/detik yang didapatkan relatif kecil.
Sedangkan pada saat menggunakan memcached, yang paling banyak menggunakan CPU adalah php-fpm.
Pada saat menggunakan memcached, aplikasi tidak melakukan eksekusi query SQL dikarenakan hasil dari query tersebut masih disimpan dalam cache. Sehingga, utilisasi SQL Server tetap rendah dan resource CPU dapat digunakan sepenuhnya oleh php-fpm untuk merespon seluruh request yang datang.
Dari perbandingan di atas, terlihat bagaimana implementasi memcached dapat berpotensi mengurangi biaya server. Memcached dapat membantu mengurangi beban pada server database, sehingga resource yang dibutuhkan tidak setinggi jika dibandingkan tanpa menggunakan memcached.
Selain itu, karena aplikasi dapat menangani lebih banyak request, maka dapat meningkatkan user experience yang berpotensi dapat meningkatkan average revenue per user (ARPU). Soal ARPU ini mungkin kita bahas lebih detil di lain waktu ya :)
Tanpa Memcached | Dengan Memcached | |
1000 sequential request | 30-35 request per detik | 178 request per detik |
1000 concurrent request | 30-35 request per detik | 1600-1700 request per detik |
Utilisasi CPU tertinggi | SQL Server | php-fpm |
Tips dan Strategi Implementasi
Untuk dapat memaksimalkan memcached dalam meningkatkan performance aplikasi, terdapat beberapa tips yang perlu diperhatikan:
Gunakan waktu expire yang dapat menyeimbangkan efisiensi cache dan relevansi data. Waktu expire yang terlalu panjang/lama dapat meningkatkan efisiensi cache, namun dapat berdampak pada data di cache yang sudah tidak relevan sehingga perlu di-refresh. Sedangkan waktu expire yang terlalu cepat dikhawatirkan tidak banyak membantu meningkatkan performance karena akan terlalu sering mengambil data baru.
Utamakan cache data yang read-intensive, bukan write-intensive. Jika kita cache data yang sering berubah nilainya, kita akan direpotkan karena harus sering melakukan refresh data. Utamakan cache data yang tidak terlalu sering berubah nilainya, contohnya seperti konfigurasi aplikasi.
Pantau penggunaan memcached. Konsisten memantau penggunaan memcached seperti berapa kapasitas memory yang sudah digunakan, tingkat hit/miss. Beberapa metrik tersebut dapat memberikan gambaran apakah strategi implementasi kita sudah tepat atau masih perlu perbaikan.
Gunakan memcached untuk menyimpan beberapa jenis objek. Selain dapat digunakan untuk menyimpan hasil query SQL seperti pada tes di atas, memcached juga dapat digunakan untuk menyimpan objek lain seperti halaman HTML dan sebagai media untuk menyimpan session.
Sebetulnya masih ada beberapa tips yang dapat dilakukan, namun hanya dengan mengikuti tips-tips dasar di atas sebetulnya sudah dapat memberikan dampak yang cukup signifikan. Selamat mencoba ya :)