Raspberry Pi 400 has sufficient power to run full-featured microservices written in Swift. Running Swift (together with MongoDB) on such a small gadget is serious fun!
I’ve tested this setup on Raspberry PI 400 which has a quad core processor, 4 GB of RAM and a speedy USB 3.0 SSD, however the instructions below are not limited only to this device.
Even though base configuration was not overclocked, I’ve managed to run simple Vapor-based microservice, and achieve over 10 000 req/sec on this little piece of silicon!
If you want to use the latest Vapor 4, you need to upgrade Raspberry PI OS to 64 bits. Otherwise, this step may be skipped.
Ideal setup, as of 01/2020 is:
For IDE we will use:
Swift ARM builds are available here: https://packagecloud.io/swift-arm/release. Unfortunatelly, the latest version for Rasperry PI OS (default distribution) is 5.1.3 and it’s not usable with the latest Vapor 4 version. We need to upgrade the operating system to 64 bits.
https://packagecloud.io/swift-arm/release/packages/debian/buster/swiftlang_5.3.1-3-debian-buster_arm64.deb
with dpkg -i
swapoff -a
dd if=/dev/zero of=/media/[yourssd]/swap ibs=1M obs=1M count=5000
mkswap /media/[yourssd]/swap
swapon /media/[yourssd]/swap
swift package init --type executable
swift build
https://github.com/apple/sourcekit-lsp
to use the Auto-Completion functionality in Visual Studio Code, because version 5.3.1 is unusably slow. The new version is 10 times more performant. We will compile it from sources using this documentation here.
This will work for arm64:swift build -c release -Xcxx -I/usr/lib/swift -Xcxx -I/usr/lib/swift/Block
cp .build/aarch64-unknown-linux-gnu/release/sourcekit-lsp /usr/local/bin/sourcekit-lsp
apt-get install npm
cd Editors/vscode
npm run createDevPackage
code --install-extension ./out/sourcekit-lsp-vscode-dev.vsix
After installation, every feature should work well, including: autocompletion, fix-its, documentation, go to definition. If not, it’s probably because of the internal card speed - see below how to improve the performance by a factor of 10.
SD cards tend to be slow. I recommend to either boot from an SSD entirely, or boot from an SD card, but in this case move the essential data to faster drive. It makes a huge difference during development.
Directories to move to external faster drive:
~/.config/Code (for Visual Studio Code)
~/.cache (for various developmnt tasks)
/tmp (e.g. lsp cache)
You can tune your system for maximum performance:
fs.inotify.max_user_watches=524288
cd /sys/devices/system/cpu
echo performance > cpu0/cpufreq/scaling_governor
echo performance > cpu1/cpufreq/scaling_governor
echo performance > cpu2/cpufreq/scaling_governor
echo performance > cpu3/cpufreq/scaling_governor
echo performance > cpu4/cpufreq/scaling_governor
Ok, this is an optional step. Chances are, your microservice needs a database, such as MongoDB. Yes, it works just fine, but you need to compile it from sources.
You need at least 20 GB of free space for compilation. Compilation will take at least 5-10 hours.
We will compile as usual using https://github.com/mongodb/mongo/blob/master/docs/building.md
, but have to provide additional flag since there are problems with crc32 because of missing instructions. More information here
Using flag --use-hardware-crc32=off
will compile it fine. Full script should look similar to this:
git clone https://github.com/mongodb/mongo.git
python3 -m vevn virtualenv
source virtualenv/bin/activate
python3 buildscripts/scons.py install-mongod --disable-warnings-as-errors --use-hardware-crc32=off
Congratulations, after 5-10 hours, you will get the 4,2 GB binary file called mongodb
. It’s time to strip it to just ~40 MB with the instructions below:
root@raspberrypi:/media/pi/rpi/mongo# ls build/install/bin/mongod
build/install/bin/mongod
root@raspberrypi:/media/pi/rpi/mongo# strip build/install/bin/mongod
root@raspberrypi:/media/pi/rpi/mongo# cp build/install/bin/mongod /usr/local/bin
Now it’s time to prepare a storage space for a database and logs. Use your external drive and mount it somewhere. E.g. create mongo-data
and mongo-logs
directories, and use the following configuration files as examples.
I used the simplest configuration possible. I recommend changing the default user pi
, for security reasons.
root@raspberrypi:/media/pi/rpi/mongo# cat /etc/systemd/system/mongodb.service
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network-online.target
Wants=network-online.target
[Service]
User=pi
Group=adm
#EnvironmentFile=-/etc/default/mongod
ExecStart=/usr/local/bin/mongod --config /etc/mongod.conf
PIDFile=/var/run/mongodb/mongod.pid
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings
[Install]
WantedBy=multi-user.target
And this is the counterpart /etc/mongod.conf
file.
# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# Where and how to store data.
storage:
dbPath: /media/[yourssd]/mongo-data
journal:
enabled: true
# engine:
# wiredTiger:
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /media/[yourssd]/mongo-logs/mongo.log
# network interfaces
net:
port: 27017
bindIp: 127.0.0.1
# how the process runs
processManagement:
timeZoneInfo: /usr/share/zoneinfo
#security:
#operationProfiling:
#replication:
#sharding:
## Enterprise-Only Options:
#auditLog:
#snmp:
Now, it’s time to run it!
systemctl daemon-reload
service mongodb start
Check your logs directory for troubleshooting with journalctl -u mongodb.service
.
Congratulations!
I hope you will have as much fun as I did with this. Feel free to leave any comments or suggestions below. Thanks for trying it out!