VPS Dedicated CPU showdown : Linode vs DigitalOcean

This Feb, Linode releases new plans (Dedicated CPU VPS plans, which means the CPUs run on KVM host without sharing to other neighbors). So I make this benchmark to show how good it is compared with DigitalOcean (DO) in the same plan.

Price

Linode’s price has 25% lower than DO’s.

Linode price

linode dedicated cpu price

DigitalOcean price

digitalocean dedicated cpu price

Boot time

Linode VPS boots a bit slower than DO. (115 processes vs 96 processes)

Benchmark

I used this script (https://github.com/n-st/nench) to benchmark the minimum plan (2 vCPUs and 4GB RAM). I configured vm.swappiness = 0 to disable swap.

Linode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Processor:    Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
CPU cores: 2
Frequency: 2499.984 MHz
RAM: 3.9G
Swap: 511M
Kernel: Linux 4.15.0-43-generic x86_64

Disks:
sda 24.5G HDD
sdb 512M HDD

CPU: SHA256-hashing 500 MB
3.339 seconds
CPU: bzip2-compressing 500 MB
5.649 seconds
CPU: AES-encrypting 500 MB
1.535 seconds

ioping: seek rate
min/avg/max/mdev = 60.1 us / 87.6 us / 8.98 ms / 104.1 us
ioping: sequential read speed
generated 25.2 k requests in 5.00 s, 6.15 GiB, 5.04 k iops, 1.23 GiB/s

dd: sequential write speed
1st run: 953.67 MiB/s
2nd run: 1239.78 MiB/s
3rd run: 1144.41 MiB/s
average: 1112.62 MiB/s

IPv4 speedtests
your IPv4: 139.162.5.xxxx

Cachefly CDN: 54.08 MiB/s
Leaseweb (NL): 6.64 MiB/s
Softlayer DAL (US): 3.18 MiB/s
Online.net (FR): 1.74 MiB/s
OVH BHS (CA): 0.29 MiB/s

IPv6 speedtests
your IPv6: 2400:8901::xxxx

Leaseweb (NL): 5.60 MiB/s
Softlayer DAL (US): 0.00 MiB/s
Online.net (FR): 10.43 MiB/s
OVH BHS (CA): 0.85 MiB/s
-------------------------------------------------

Digital Ocean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Processor:    Intel(R) Xeon(R) Platinum 8168 CPU @ 2.70GHz
CPU cores: 2
Frequency: 2693.670 MHz
RAM: 3.9G
Swap: -
Kernel: Linux 4.15.0-45-generic x86_64

Disks:
vda 25G HDD

CPU: SHA256-hashing 500 MB
2.427 seconds
CPU: bzip2-compressing 500 MB
4.252 seconds
CPU: AES-encrypting 500 MB
0.964 seconds

ioping: seek rate
min/avg/max/mdev = 114.8 us / 185.5 us / 4.33 ms / 48.3 us
ioping: sequential read speed
generated 4.13 k requests in 5.00 s, 1.01 GiB, 826 iops, 206.6 MiB/s

dd: sequential write speed
1st run: 410.08 MiB/s
2nd run: 386.24 MiB/s
3rd run: 417.71 MiB/s
average: 404.68 MiB/s

IPv4 speedtests
your IPv4: 178.128.214.xxxx

Cachefly CDN: 13.14 MiB/s
Leaseweb (NL): 13.56 MiB/s
Softlayer DAL (US): 7.82 MiB/s
Online.net (FR): 9.86 MiB/s
OVH BHS (CA): 0.44 MiB/s

IPv6 speedtests
your IPv6: 2400:6180:0:xxxx

Leaseweb (NL): 9.57 MiB/s
Softlayer DAL (US): 0.00 MiB/s
Online.net (FR): 4.95 MiB/s
OVH BHS (CA): 0.30 MiB/s
-------------------------------------------------

Conclusion

DigitalOcean allows you run on newer hardwares so its CPU is better (~43%) than Linode’s. (You can compare the result in CPU hashing section). By the way, Linode has the better price so it’s your choices! :)

Hope Linode will upgrade all hardwares soon. Updated : they have new CPUs in some datacenters which are Intel Xeon Gold 6148 and AMD EPYC 7501, so stay tuned!

#TIL : Run shell command in all hosts

To run a shell command in all hosts, you can use the module name raw and provide shell command to module args.

Example:

  • To list all CPU model name of hosts
1
$ ansible all -m raw -a "cat /proc/cpuinfo | grep 'model name'"

#TIL : Can not run downloaded binary inside alpine linux because of missing shared libs

Alpine linux becomes the most base image for docker images because it’s lightweight and handful package manager apk. Sometimes, you create an image that downloads the binary file but can not execute it. It shows something like this:

1
/entrypoint.sh: line ***: [your binary]: not found

The problem is your binary built within shared libraries, so it can’t run without shared libraries dependencies. To findout which libraries is missing, use this

1
$ ldd [your binary path]

This is sample result

1
2
3
4
5
6
7
8
/usr/local/bin # ldd hugo
/lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
Error loading shared library libstdc++.so.6: No such file or directory (needed by hugo)
libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)
Error loading shared library libgcc_s.so.1: No such file or directory (needed by hugo)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fa852f2a000)

So we need to install libstdc++ and libc6-compat before run the binary

1
RUN apk add --no-cache libstdc++ libc6-compat

Boost Docker CI Build Speed to ~10X times

As an software engineering developer, you know that automated CI testing is one of keys to improve software release life-cycle.

But sometimes reality is not as good as you think, CI testing speed is slow (3-10 minutes / build) and it slows the release cycle speed down. And you try to look into your build logs to find out what causes the problem. Then you got it, it’s mostly the DATABASE service (MySQL, Postgres, MongoDB, …)

I will summarize some stages of your database in a testing build:

  • First, it initializes the data, loads config and listens to the connections (takes around 10-45 seconds)
  • Second, that you import your testing database into the server (including schemas and initialized data) takes around 20-60 seconds
  • Then, on each test case, it needs to clear all data then re-imports fixture data (takes around 30-120 seconds)

So how to make these servers run as fast as possible like some Key-Value databases do? (Redis, Memcached). The main different point is the MEMORY! What if we put all data inside memory??

All of we know that RAM speed with 150 times lower latency is technically better than SSD and HDD speed. And as a matter of fact, Linux is a good OS that supports a lot of filesystems, specially tmpfs, which you can mount files into your RAM memory.

However, nothing is perfect and this is not an exception. Actually, it is not a good option for persistent data which is not necessary for testing database. What it really needs is speed only, so it fits in.

That’s my idea, now I will try to test it on my CI environment (I use DroneCI using Docker). In new version 0.8+ of DroneCI, they support us to run docker containers within tmpfs mount.

So I just add this line into my drone config

1
2
3
4
5
6
7
8
9
services:
testdatabase:
thumbnail: mysql:5.7
# Add this 2 lines below to boost your database container
tmpfs:
- /var/lib/mysql
environment:
- MYSQL_DATABASE=testdb
- MYSQL_ROOT_PASSWORD=passwd

Result:

  • MySQL service initializes in 3 seconds instead of 25 seconds
  • Import testing database using mysql client takes below 1 second instead of 17 seconds
  • My test cases run 20-30% faster (I have few testcases using database)

So, worth a shot !!


Ref:

Refactoring Code - Day 2 - Các nguyên lý cơ bản trong refactoring

Hôm nay mình tiếp tục đọc phần II của cuốn sách “Priciples in Refactoring”. Phần này có lẽ là phần quan trọng nhất của cuốn sách nên mình sẽ đọc và nghiền ngẫm từ từ từng mục một. Dưới đây là những ghi chép ngẫu hứng tóm tắt lại 2 mục con của phần II:

Định nghĩa của Refactoring

  1. Refactoring là thay đổi cấu trúc bên trong của phần mềm làm cho nó “dễ hiểu hơn” và “rẻ hơn” cho việc thay đổi mà không thay đổi hành vi có thể quan sát được => End-user sẽ không thể cảm nhận có sự thay đổi bên trong phần mềm.

  2. Refactoring giống với Performance Optimization là thay đổi cấu trúc bên trong mà không thay đổi hành vi quan sát được. Nhưng lại khác nhau về mục đích: Performance Optimization thường làm code khó hiểu hơn để đổi lại hiệu năng khi cần thiết.

Tại sao phải dùng Refactoring?!

  1. Cải thiện thiết kế phần mềm. Refactoring thường xuyên sẽ giúp code giữ nguyên được hình dáng của thiết kế. Không những thế nó giúp làm tinh gọn những thiết kế nghèo nàn bằng cách giảm đi sẽ lặp đi lặp lại để đảm bảo rằng code chỉ thể hiện đúng 1 và chỉ 1 hành vi duy nhất của nó. Đó là bản chất của một thiết kế tốt.

  2. Làm cho phần mềm dễ hiểu hơn. Dù muốn hay không thì dự án phần mềm sẽ luôn xuất hiện thêm kể thứ 3 ngoài bạn và khách hàng, đó là những lập trình viên khác trong tương lai. Vì thế việc máy tính phải xử lý thêm vài vòng tính toán làm nó chậm đi cũng không quan trọng bằng vấn đề một thay đổi phải mất hàng tháng mà lẽ ra chỉ mất hàng giờ hết người lập trình viên hiểu rõ code của bạn. Ngoài ra, hãy dùng code để diễn tả ý tưởng của bạn, biến code trở thành công cụ ghi chép chủ đạo chứ không phải ghi nhớ trong trí nhớ hoặc viết vào một nơi khác.

  3. Giúp bạn tìm ra bugs dễ hơn. Một khi đã hiểu rõ code một cách rõ ràng, bạn sẽ phần nào đó xoá bở bớt những giả tưởng mơ hồ về hệ thống, từ đó có thể tìm ra lỗi dễ dàng hơn.

  4. Giúp bạn lập trình nhanh hơn (trong tương lai). Một thiết kế hệ thống tốt là thiết yếu cho việc phát triển nhanh hệ thống. Refactoring giúp cải thiện thiết kế hệ thống, giúp bạn đi theo đúng thiết kế => nó sẽ làm tăng tốc độ phát triển hệ thống lên là điều tất yếu!

Hôm nay mình chỉ đọc đến đây thôi vì phần này quan trọng mình không muốn sẽ bị quá tải về kiến thức, “giục tốc bất đạt” mà ;) có thể bạn sẽ thấy mình lặp ý trong các bài liên tục, cái này mình sẽ tổng hợp lại sau khi lĩnh hội xong cuốn sách :)


Nếu bạn muốn mua và tìm đọc cuốn sách thì nhấn vào đây

Ref:

  • Cover photo from Google Search

Refactoring Code - Day 1 - Cơ bản về refactoring

Hôm rài qua nha ông anh chôm (mượn) được cuốn sách kinh điển gối đầu giường của dân Dev. Cuốn sách này là “REFACTORING” của Martin Fowler bản năm 1999 hướng dẫn trên ngôn ngữ Java (có bản 2018 mới trên cũng trên nền Java… nhưng thêm chữ Script 😁 - JavaScript, nhưng theo mình cảm nhận thì nó không tường minh như là trên Java). Và đây là bìa cuốn sách:

Refactoring Book Cover 1999

Hôm nay mình đọc được hết phần 1 gồm 52 trang đầu của sách và cảm nhận được mình học được rất nhiều từ phần này, sau đây là những ghi chép ngẫu hứng tóm tắt lại phần I của mình:

  1. Refactoring bản chất là thay đổi cấu trúc code bên trong nhưng không thay đổi hành vi bên ngoài của code. (Nôm na là bạn học nhiều sẽ thông minh ra nhưng cơ thể bên ngoài vẫn phải vậy) => Vì thế đòi hỏi việc đầu tiên và quan trọng nhất trước khi refactoring là phải có một bộ test tốt.

  2. Nhịp điệu chính (thần chú bạn luôn nên nhớ) khi làm refactoring là thay đổi nhỏ -> test -> thay đổi nhỏ -> test -> thay đổi nhỏ -> … -> hoàn thành -> commit

  3. Code tốt là code tự nó giải thích được bản thân nó là gì, làm gì và chạy ra sao. Và chìa khoá trong việc này là cách đặt tên biến và phương thức. (nếu mọi thứ chưa tường minh thì mới dùng comments) => Đừng ngại trong việc đổi tên nếu nó làm code tường minh, rõ ràng hơn.

  4. Nên giải thoát cho các biến tạm thời không cần thiết, vì nó có thể bị lãng quên và dễ nảy sinh ra vấn đề sau này. => Có thể áp dụng chiến thuật “Replace Temp with Query”

  5. Đừng ngại refactoring sẽ làm chậm chương trình cho tới khi bạn có số liệu profiler chính xác. Và lúc đó thì chuyện tối ưu cũng sẽ dễ hơn là tối ưu trên một đống hỗn tạp phải không?! => Khi refactoring thì tính rõ ràng được ưu tiên hơn hiệu suất.

  6. Ưu tiên tách business logic ra khỏi giao diện để nâng cao tính tái sử dụng.

  7. Và cuối cùng nhưng không kém quan trọng là mục tiêu chính của refactoring:

    • Làm code tinh gọn hơn
    • Rõ ràng hơn, minh bạch hơn (No magic)
    • Dễ test hơn
    • Sẵn sàng cho những thay đổi trong tương lai hơn

PHẦN NÀY TỚI ĐÂY LÀ HẾT RÙI !!


Nếu bạn muốn mua và tìm đọc cuốn sách thì nhấn vào đây

Ref:

  • Cover photo from Google Search
  • “Refactoring - Improving Design Existing Code” book cover from Amazon

SaaS Multi-tenant Architecture - Part 1

What is SaaS Multi-tenant?

SaaS (Software as a Service) or “on-demand software” has become a common delivery model for many bussiness software applications nowaday. It means when customers register the service, they get the software right-away.

In case customer want an isolated software (means other customers can’t read and write their data), then the multi-tenant architecture is your right choice !

Common strategies

We have many ways to build a multi-tenant system, but there are 3 common strategies:

  • Shared database, shared schemas
  • Shared database, seperated schemas
  • Separated database

Every strategy has pros and cons and nothing in software is silver bullet. So pick the strategy fit to your requirements.

Separated database

But today, I will write about my chosen strategy (Separated database).

The most important things you have to remember is what being shared and separated between different tenants:

  • SHARED
    • Infrastructures
      • Hosts
      • Networking
    • Platforms
      • Load balancer
      • Databases
      • Key-Value storages
      • Monitoring
    • Software
      • Application tenant code
  • SEPARATED
    • Database
    • Metadata (about tenant info)
    • Environment variables
    • File storages
    • Subscription Plans
    • Endpoints
    • Queues (job queues)

To be continued …


Ref:
- Cover photo from hackernoon