How can you measure VM performance (CPU, Disk, Latency, Concurrent Users etc) on Ubuntu and comparing Vultr, Digital Ocean and UpCloud – Part 4 of 4
Read Part 1, Part 2, Part 3 or Part 4
I ran the MySQL benchmark preparation command again (no problem this time).
sysbench --test=oltp --oltp-table-size=1000000 --db-driver=mysql --mysql-db=test --mysql-user=root --mysql-password=###################### prepare sysbench 0.4.12: multi-threaded system evaluation benchmark Creating table 'sbtest'... Creating 1000000 records in table 'sbtest'...
Test table and records created
Now I can benchmark MySQL on my main server.
sysbench --test=oltp --oltp-table-size=1000000 --db-driver=mysql --mysql-db=test --mysql-user=root --mysql-password=################################# --max-time=60 --oltp-read-only=on --max-requests=0 --num-threads=8 run
RAW Output
sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 8 Doing OLTP test. Running mixed OLTP test Doing read-only test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Threads started! Time limit exceeded, exiting... (last message repeated 7 times) Done. OLTP test statistics: queries performed: read: 336210 write: 0 other: 48030 total: 384240 transactions: 24015 (400.09 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 336210 (5601.24 per sec.) other operations: 48030 (800.18 per sec.) Test execution summary: total time: 60.0242s total number of events: 24015 total time taken by event execution: 480.0242 per-request statistics: min: 1.79ms avg: 19.99ms max: 141.00ms approx. 95 percentile: 37.49ms Threads fairness: events (avg/stddev): 3001.8750/27.36 execution time (avg/stddev): 60.0030/0.01
Results
queries performed (in 60 seconds):
- read: 336210
- other: 48030
- total: 384240
I decided to add an index to see if I can speed this query up (read the MySQL index page here). I added an index (in Adminer) on the columns “Id” and “pad” for the sbtest table in the test database
I restarted the MySQL process
mysql restart [ ok ] Restarting mysql (via systemctl): mysql.service.
I ran the same benchmark again.
Raw Output
sysbench --test=oltp --oltp-table-size=1000000 --db-driver=mysql --mysql-db=test --mysql-user=root --mysql-password=########################## --max-time=60 --oltp-read-only=on --max-requests=0 --num-threads=8 run sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 8 Doing OLTP test. Running mixed OLTP test Doing read-only test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Threads started! Time limit exceeded, exiting... (last message repeated 7 times) Done. OLTP test statistics: queries performed: read: 426538 write: 0 other: 60934 total: 487472 transactions: 30467 (507.69 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 426538 (7107.67 per sec.) other operations: 60934 (1015.38 per sec.) Test execution summary: total time: 60.0110s total number of events: 30467 total time taken by event execution: 479.9124 per-request statistics: min: 5.75ms avg: 15.75ms max: 138.57ms approx. 95 percentile: 25.10ms Threads fairness: events (avg/stddev): 3808.3750/8.70 execution time (avg/stddev): 59.9891/0.00
Results
The quick index added 20% extra throughput on queries 🙂
Don’t forget to delete your test database
DROP DATABASE `test`;
Viewing MySQL Index Usage (on the “test” database)
Query to show Index stats for a table ‘test’
SELECT OBJECT_SCHEMA as 'Database', OBJECT_NAME as 'Table', INDEX_NAME as 'Index', COUNT_STAR, SUM_TIMER_WAIT, MIN_TIMER_WAIT, AVG_TIMER_WAIT, MAX_TIMER_WAIT, COUNT_READ, SUM_TIMER_READ, MIN_TIMER_READ, AVG_TIMER_READ, MAX_TIMER_READ, COUNT_FETCH, SUM_TIMER_FETCH, MIN_TIMER_FETCH, AVG_TIMER_FETCH, MAX_TIMER_FETCH FROM performance_schema.table_io_waits_summary_by_index_usage WHERE object_schema = 'test'
I can see the MySQL PRIMARY index is getting used 🙂
Read more in viewable query stats (columns) here.
Other System Information Tools
Show processor information
cat /proc/cpuinfo
Output
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 61 model name : Virtual CPU a7769a6388d5 stepping : 2 microcode : 0x1 cpu MHz : 2394.454 cache size : 16384 KB physical id : 0 siblings : 1 core id : 0 cpu cores : 1 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single kaiser fsgsbase bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass bogomips : 4788.90 clflush size : 64 cache_alignment : 64 address sizes : 40 bits physical, 48 bits virtual power management:
Memory Information
You can assign 512MB, 1GB, 2GB or more memory to a server on Vultr, Read my guide here on upgrading resources for Vultr VM’s here.
Only upgrade your server’s memory when server processes demand it, there is no need to pay for extra idle memory. Read my older guides on upgrading Digital Ocean and AWS servers.
I use the htop utility to monitor memory and processes. The memory usage will depend on how you have configured your server to use connection pools in code, MySQL or services. Also what memory demands do you get in pean bandwidth times?
You can check your server memory details on Ubuntu with this command
cat /proc/meminfo
Output
MemTotal: 2048104 kB MemFree: 96176 kB MemAvailable: 693072 kB Buffers: 183476 kB Cached: 526124 kB SwapCached: 0 kB Active: 1467220 kB Inactive: 243228 kB Active(anon): 1070464 kB Inactive(anon): 27004 kB Active(file): 396756 kB Inactive(file): 216224 kB Unevictable: 3652 kB Mlocked: 3652 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 64 kB Writeback: 0 kB AnonPages: 1004504 kB Mapped: 114664 kB Shmem: 94192 kB Slab: 192692 kB SReclaimable: 171892 kB SUnreclaim: 20800 kB KernelStack: 3072 kB PageTables: 20528 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 1024052 kB Committed_AS: 2424332 kB VmallocTotal: 34359738367 kB VmallocUsed: 0 kB VmallocChunk: 0 kB HardwareCorrupted: 0 kB AnonHugePages: 247808 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 67440 kB DirectMap2M: 2029568 kB
Use Memory or Disk (Swap)
You can configure the use of Memory over Disk by configuring your/etc/sysctl.conf file (setting value “vm.swappiness”)
You can check your swap file settings by running the following command
cat /proc/sys/vm/swappiness 1
Or By running
sysctl vm.swappiness vm.swappiness = 1
Set a new swap file value by editing /etc/sysctl.conf
sudo nano /etc/sysctl.conf
Set the following to use more ram over the swap disk.
vm.swappiness = 1
Read about swappiness values here: https://en.wikipedia.org/wiki/Swappiness
Service Performance
Performance (and allocated resources) depends on the demands of your operating system and installed software
What operating system do you have?
lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04.4 LTS Release: 16.04 Codename: xenial
View NGINX Status, how much memory does it use?
/etc/init.d/nginx status ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2018-05-25 21:28:25 AEST; 1 weeks 3 days ago Docs: man:nginx(8) Main PID: #### (nginx) Tasks: 3 Memory: 58.9M CPU: 33min 11.515s CGroup: /system.slice/nginx.service ├─#### nginx: master process /usr/sbin/nginx -g daemon on; master_process on; ├─#### nginx: worker process └─#### nginx: cache manager process
PHP (and Child Worker) status how much memory does it use and how many child workers do you have? Read my add PHP child workers post here (and update to PHP 7.2 here)
sudo service php7.2-fpm status ● php7.2-fpm.service - The PHP 7.2 FastCGI Process Manager Loaded: loaded (/lib/systemd/system/php7.2-fpm.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2018-05-25 21:28:26 AEST; 1 weeks 3 days ago Docs: man:php-fpm7.2(8) Main PID: #### (php-fpm7.2) Status: "Processes active: 0, idle: 20, Requests: 75911, slow: 0, Traffic: 0.1req/sec" Tasks: 21 Memory: 694.2M CPU: 20h 49min 45.132s CGroup: /system.slice/php7.2-fpm.service ├─ #### php-fpm: master process (/etc/php/7.2/fpm/php-fpm.conf) ├─ #### php-fpm: pool www-acc ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-acc ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr ├─ #### php-fpm: pool www-usr └─ #### php-fpm: pool www-usr
MySQL Status
sudo service mysql status ● mysql.service - MySQL Community Server Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2018-05-25 21:28:27 AEST; 1 weeks 3 days ago Main PID: ##### (mysqld) Tasks: 35 Memory: 405.9M CPU: 2h 17min 31.822s CGroup: /system.slice/mysql.service └─#### /usr/sbin/mysqld
Shared VM Hosts
One of the biggest impacts (after server latency) for your server is not the disk performance but the number of hosts/websites on the server who are also using the disk and server resources.
I have 80 other web servers on my server (based on a reverse lookup).
I may move to a dedicated box when I can afford it.
Security
Above all else ensure that security is number 1 priority and make performance second priority.
Scan your site with Zap, Qualys and Kali Linux. Performance means nothing if you are hacked.
Simulated concurrent users
You can use Siege to test the maximum concurrent users accessing your site before the server starts to drop connections.
FYI: If you use Cloudflare (you should) this may not work as it will block connections.
Install Siege
sudo apt-get install siege
Test your server with 10 concurrent serves for 1 minute
siege -t1m c10 'https://yourserver.com/'
Results
siege -t1m c10 'https://yourserver.com/' ** SIEGE 3.0.8 ** Preparing 15 concurrent users for battle. The server is now under siege... Lifting the server siege... done. Transactions: 417 hits Availability: 100.00 % Elapsed time: 59.01 secs Data transferred: 8.24 MB Response time: 1.62 secs Transaction rate: 7.07 trans/sec Throughput: 0.14 MB/sec Concurrency: 11.46 Successful transactions: 417 Failed transactions: 0 Longest transaction: 2.26 Shortest transaction: 1.49
Keep upping the connections (from 10 above) to a limit where connections start dropping.
I tried 25 then 50 concurrent users hitting a server on Digital Ocean and it did not fail.
Conclusion
- Choose a server near your customers
- Change hosts if one is faster and cheaper
- Measure or benchmark your server (and compare over time).
- Use Cloudflare
Create your own server today
- Create your own server on Vultr here.
- Create your own server on Digital Ocean here.
- Create your own server on UpCloud here.
And remember you can install the Runcloud server management dashboard here.
I hope this guide helps someone.