Intro
I was running a new daemon on my server, factomd, to experiment with digital currency. It’s an old m1.small instance with only 1.7 GB of memory. The first few times I ran it it would 70000 or so blocks, I would let it run overnight, and then it would run out of memory and crash. My admin skills are a little rusty and dated but I eventually realized that adding swap space to my server could help.
The details
I’ve been running this server for five years and never bothered to create a swap area, as it turns out. My CentOS version is, I think, version 6.0, but it’s hard to tell at this point. Anyway, this command shows the lack of an active swap space:
$ sudo swapon ‐s
Filename Type Size Used Priority |
Filename Type Size Used Priority
What to do?
Amazon has introduced SSD storage and that is recommended for high I/O demands. That makes sense to me to use for swap, which is basically an extension of your memory. It’s also inexpensive in small volumes. I decided to create a 2 GB swap file – roughly the same size as the machine’s physical memory. So I bought a gp2 – general purpose – SSD volume of 2 GB. It’s only $0.20/month!
Where did it go?
After attaching it to my instance, I got what is apparently a one-time message saying what device it would appear as on my instance – /dev/sdg. I was a little nervous – justifiably as it turns out – that I would not see it from CentOS. I tried to mount it – no go. Then I did Internet research and found these two informative commands:
$ sudo lsblk ‐‐output NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,LABEL
NAME TYPE SIZE FSTYPE MOUNTPOINT LABEL
xvdj disk 100G ext4 /mnt/vol
xvde disk 6G
`-xvde1 part 6G ext4 /
xvde3 disk 896M swap
xvdk disk 2G |
NAME TYPE SIZE FSTYPE MOUNTPOINT LABEL
xvdj disk 100G ext4 /mnt/vol
xvde disk 6G
`-xvde1 part 6G ext4 /
xvde3 disk 896M swap
xvdk disk 2G
and
$ sudo fdisk ‐l
Disk /dev/xvdj: 107.4 GB, 107374182400 bytes
255 heads, 63 sectors/track, 13054 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/xvde: 6442 MB, 6442450944 bytes
255 heads, 63 sectors/track, 783 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xaae7682d
Device Boot Start End Blocks Id System
/dev/xvde1 * 1 783 6289416 83 Linux
Disk /dev/xvde3: 939 MB, 939524096 bytes
255 heads, 63 sectors/track, 114 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/xvdk: 2147 MB, 2147483648 bytes
22 heads, 16 sectors/track, 11915 cylinders
Units = cylinders of 352 * 512 = 180224 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x83d4c8ed |
Disk /dev/xvdj: 107.4 GB, 107374182400 bytes
255 heads, 63 sectors/track, 13054 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/xvde: 6442 MB, 6442450944 bytes
255 heads, 63 sectors/track, 783 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xaae7682d
Device Boot Start End Blocks Id System
/dev/xvde1 * 1 783 6289416 83 Linux
Disk /dev/xvde3: 939 MB, 939524096 bytes
255 heads, 63 sectors/track, 114 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/xvdk: 2147 MB, 2147483648 bytes
22 heads, 16 sectors/track, 11915 cylinders
Units = cylinders of 352 * 512 = 180224 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x83d4c8ed
Turns out I had a swap file all along but had never activated it! Further, both these commands show that the new volume is appearing as xvdk, not xvdg. Go figure. I guess I had an xvdj volume and it took the next available letter. The mount command also showed me which of the above volumes was in use so I could see which had been added.
Then I used fdisk to create a swap space on it:
$ fdisk /dev/xvdk
Command (m for help): c
DOS Compatibility flag is not set
Command (m for help): u
Changing display/entry units to sectors
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First sector (2048-4194303, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-4194303, default 4194303):
Using default value 4194303
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks. |
Command (m for help): c
DOS Compatibility flag is not set
Command (m for help): u
Changing display/entry units to sectors
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First sector (2048-4194303, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-4194303, default 4194303):
Using default value 4194303
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
$ ls /dev/xvdk*
$ sudo mkswap /dev/xvdk1
Setting up swapspace version 1, size = 2096124 KiB
no label, UUID=0d782596-03e6-48fd-a0fa-2d0e3174f727 |
Setting up swapspace version 1, size = 2096124 KiB
no label, UUID=0d782596-03e6-48fd-a0fa-2d0e3174f727
$ sudo swapon /dev/xvdk1
The previous command activated our new swap file. To show that we run this command:
$ sudo swapon ‐s
Filename Type Size Used Priority
/dev/xvdk1 partition 2096120 0 -1 |
Filename Type Size Used Priority
/dev/xvdk1 partition 2096120 0 -1
Finally to make this swap partition persist after a reboot I added this line to /etc/fstab:
/dev/xvdk1 swap swap defaults 0 0 |
/dev/xvdk1 swap swap defaults 0 0
Did it help?
Why yes it did! Now I am using over 900 Mb of swap space, so it was needed pretty badly in fact:
$ sudo swapon ‐s
Filename Type Size Used Priority
/dev/xvdk1 partition 2096120 945552 -1 |
Filename Type Size Used Priority
/dev/xvdk1 partition 2096120 945552 -1
. And my original motivation – keeping factomd from crashing – was achieved as well. Perhaps it wasn’t so important to use an SSD volume. Mostly the i/o per second was well below 100. But I did have the satisfaction of seeing this burst to 1000, a figure I never could have hit with a traditional drive.
Appendix
Monitoring i/o
These blockchain verifiers can be killers in terms of resource consumption on little servers like mine. The best tool for analyzing what is going on is iostat:
$ iostat ‐xz 10
Linux 2.6.32-131.17.1.el6.x86_64 (ip-10-185-21-116) 05/01/17 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.92 0.00 0.17 0.24 0.85 97.83
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 0.45 0.22 0.35 6.90 6.41 23.60 0.01 11.87 8.33 14.05 1.43 0.08
xvde 0.00 0.02 0.02 0.57 0.55 4.70 8.93 0.01 15.32 6.62 15.64 2.84 0.17
xvdep3 0.00 0.00 0.00 0.00 0.00 0.00 8.73 0.00 1.95 1.95 0.00 1.94 0.00
xvdk 0.00 0.01 0.02 0.01 0.19 0.16 11.35 0.00 3.23 0.92 10.75 0.19 0.00
avg-cpu: %user %nice %system %iowait %steal %idle
3.65 0.00 6.44 83.93 1.42 4.56
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 1.71 232.42 2.11 3440.68 30.54 14.80 0.43 1.84 1.80 6.95 1.72 40.38
xvde 0.00 0.00 74.59 3.65 3773.45 29.17 48.61 0.31 3.99 3.36 16.91 0.99 7.77
xvdk 5.47 414.93 606.78 230.37 4898.01 5162.39 12.02 1.89 2.26 0.88 5.89 0.18 14.89
avg-cpu: %user %nice %system %iowait %steal %idle
2.63 0.00 4.19 89.55 1.23 2.40
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 0.00 374.08 0.50 5435.98 4.02 14.52 0.84 2.25 2.25 4.33 1.32 49.32
xvde 0.00 0.00 3.52 0.28 185.03 2.23 49.29 0.01 1.66 1.41 4.80 0.72 0.27
xvdk 1.79 99.72 521.96 108.88 4189.94 1668.83 9.29 0.76 1.21 0.72 3.53 0.14 8.95
avg-cpu: %user %nice %system %iowait %steal %idle
8.05 0.00 7.10 72.87 8.46 3.52
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 0.00 338.02 8.25 6812.99 66.04 19.87 0.94 2.72 2.71 3.18 1.44 49.84
xvde 0.00 0.00 52.17 1.76 2317.73 14.07 43.24 0.15 2.72 2.43 11.23 0.67 3.63
xvdk 9.20 381.12 1180.58 256.16 9518.27 5098.24 10.17 1.95 1.36 0.78 4.04 0.14 20.65
... |
Linux 2.6.32-131.17.1.el6.x86_64 (ip-10-185-21-116) 05/01/17 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.92 0.00 0.17 0.24 0.85 97.83
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 0.45 0.22 0.35 6.90 6.41 23.60 0.01 11.87 8.33 14.05 1.43 0.08
xvde 0.00 0.02 0.02 0.57 0.55 4.70 8.93 0.01 15.32 6.62 15.64 2.84 0.17
xvdep3 0.00 0.00 0.00 0.00 0.00 0.00 8.73 0.00 1.95 1.95 0.00 1.94 0.00
xvdk 0.00 0.01 0.02 0.01 0.19 0.16 11.35 0.00 3.23 0.92 10.75 0.19 0.00
avg-cpu: %user %nice %system %iowait %steal %idle
3.65 0.00 6.44 83.93 1.42 4.56
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 1.71 232.42 2.11 3440.68 30.54 14.80 0.43 1.84 1.80 6.95 1.72 40.38
xvde 0.00 0.00 74.59 3.65 3773.45 29.17 48.61 0.31 3.99 3.36 16.91 0.99 7.77
xvdk 5.47 414.93 606.78 230.37 4898.01 5162.39 12.02 1.89 2.26 0.88 5.89 0.18 14.89
avg-cpu: %user %nice %system %iowait %steal %idle
2.63 0.00 4.19 89.55 1.23 2.40
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 0.00 374.08 0.50 5435.98 4.02 14.52 0.84 2.25 2.25 4.33 1.32 49.32
xvde 0.00 0.00 3.52 0.28 185.03 2.23 49.29 0.01 1.66 1.41 4.80 0.72 0.27
xvdk 1.79 99.72 521.96 108.88 4189.94 1668.83 9.29 0.76 1.21 0.72 3.53 0.14 8.95
avg-cpu: %user %nice %system %iowait %steal %idle
8.05 0.00 7.10 72.87 8.46 3.52
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvdj 0.00 0.00 338.02 8.25 6812.99 66.04 19.87 0.94 2.72 2.71 3.18 1.44 49.84
xvde 0.00 0.00 52.17 1.76 2317.73 14.07 43.24 0.15 2.72 2.43 11.23 0.67 3.63
xvdk 9.20 381.12 1180.58 256.16 9518.27 5098.24 10.17 1.95 1.36 0.78 4.04 0.14 20.65
...
Always mentally discard the first set of numbers when iostat starts up. It needs to initialize its counters from that reading. But this is chock full of information. The cpu time spent waiting for i/o is too high: 70 – 90 % and a lot of that can be blamed on xvdj (%util column for device xvdj). The way I see it if your i/o were instantaneous this number would drop to 0 and our cpu could be doing other more productive things, hence it shows it is a bottleneck 60% of the time. This also shows my swap, xvdk, being sometimes heavily used and not being too much a bottleneck (20% util).
Then of course there is top, which just confirms that factomd is the resource hog:
$ top
top - 11:45:12 up 1246 days, 14:49, 3 users, load average: 1.55, 1.73, 1.67
Tasks: 108 total, 1 running, 107 sleeping, 0 stopped, 0 zombie
Cpu(s): 10.6%us, 1.7%sy, 0.0%ni, 4.6%id, 82.3%wa, 0.0%hi, 0.2%si, 0.6%st
Mem: 1695600k total, 1682160k used, 13440k free, 1400k buffers
Swap: 2096120k total, 1003088k used, 1093032k free, 45348k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29702 john 20 0 2956m 1.3g 3984 S 21.4 77.9 490:35.59 factomd
... |
top - 11:45:12 up 1246 days, 14:49, 3 users, load average: 1.55, 1.73, 1.67
Tasks: 108 total, 1 running, 107 sleeping, 0 stopped, 0 zombie
Cpu(s): 10.6%us, 1.7%sy, 0.0%ni, 4.6%id, 82.3%wa, 0.0%hi, 0.2%si, 0.6%st
Mem: 1695600k total, 1682160k used, 13440k free, 1400k buffers
Swap: 2096120k total, 1003088k used, 1093032k free, 45348k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29702 john 20 0 2956m 1.3g 3984 S 21.4 77.9 490:35.59 factomd
...
Type of cpu
Just for the record here’s the type of cpu you get with an m1 small instance:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
stepping : 7
cpu MHz : 1799.999
cache size : 20480 KB
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu de tsc msr pae cx8 cmov pat clflush mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc up rep_good aperfmperf unfair_spinl
ock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt aes hypervisor lahf_lm arat epb xsaveopt pln pts
bogomips : 3599.99
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management: |
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 45
model name : Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz
stepping : 7
cpu MHz : 1799.999
cache size : 20480 KB
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu de tsc msr pae cx8 cmov pat clflush mmx fxsr sse sse2 ss ht syscall nx lm constant_tsc up rep_good aperfmperf unfair_spinl
ock pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt aes hypervisor lahf_lm arat epb xsaveopt pln pts
bogomips : 3599.99
clflush size : 64
cache_alignment : 64
address sizes : 46 bits physical, 48 bits virtual
power management:
So that’s a single 2 GHz cpu.
Conclusion
We showed how to economically add swap to a CentOS image on Amazon AWS. We showed factomd successfully running on this small instance and we showed linux commands that can be used to monitor resource consumption. Knowing what I know now – that factomd is i/o limited – in addition to creating a swap space I probably would have put its files onto its own SSD drive, which is their recommendation anyway.
References and related
I followed this post for the swap partition creation steps: http://network-howtos.blogspot.com/2015/04/adding-new-swap-partition-to-centos-vm.html