200 MB RAM FreeBSD Desktop

8 min read Original article ↗

Recently I came across Lunduke post about some mysterious Vendefoul Wolf Linux distribution that uses 217 MB RAM with Devuan as base (no systemd(1) here) and XLibre X11 server along with IceWM window manager.

For the record – the Lunduke post states 200 MB RAM but XLibreDev quotes a post where exactly 217 MB RAM is reported.

Later Lunduke even posted a video about it.



As I use similarly low resource setup with Openbox/Tint2/Dzen2 setup (documented FreeBSD Desktop here) I was wondering … how low can I go with FreeBSD RAM usage.

Lets try …

The Table of Contents is as follows.

  • Install
  • Configuration
    • /boot/loader.conf
    • /etc/rc.conf
    • /etc/sysctl.conf
    • /etc/devfs.rules
    • Installed Packages
    • Login Manager
    • ~/.xinitrc
  • Startup
  • RAM Usage
  • End Session
  • Comparison
  • Summary

Install

I wanted to use most recent FreeBSD so I used 15.0-RELEASE version – including the Tech Preview PKGBASE setup for FreeBSD Base System.

As Xorg X11 implementation is currently intentionally crippled by some Red Hat employees and some people from FreeDesktop.org I decided to use actively developed and maintained XLibre X11 server instead.

Example of such behavior below.

More on that tragic Xorg story where open source spirit died long time ago is available here:

A lot has also been explained in this message:

As the Vendefoul Wolf Linux did not used ZFS I also decided to fight fair and used UFS with Soft Updates Journaling mode that minimizes fsck(8) time to minimum. For the record Netflix also uses FreeBSD with UFS filesystem.

Using UFS would mean loosing great FreeBSD feature called ZFS Boot Environments … but fortunately you can use UFS Boot Environments as replacement on UFS filesystems.

Configuration

After install I created my vermaden user with membership in these groups.

FreeBSD $ id | tr ', ' '\n' 
uid=1000(vermaden)
gid=1000(vermaden)
groups=0(wheel)
5(operator)
44(video)
48(idletime)
69(network)
1000(vermaden)

Later I disabled additional virtual terminals that I would not use anyway in the /etc/ttys file.

/boot/loader.conf

Next used /boot/loader.conf file.

# CONSOLE COMMON
  loader_logo=none
  loader_menu_frame=none
  screen.font="6x12"

# CONSOLE RESOLUTION
  kern.vt.fb.default.mode="1920x1080"
  efi_max_resolution="1920x1080"
  vbe_max_resolution="1920x1080"

# ENABLE SYNAPTICS
  hw.psm.synaptics_support=1

# DISABLE /dev/diskid/* AND /dev/gptid/* ENTRIES FOR DISKS
  kern.geom.label.disk_ident.enable=0
  kern.geom.label.gptid.enable=0

# POWER MANAGEMENT POWER OFF DEVICES WITHOUT ATTACHED DRIVER
  hw.pci.do_power_nodriver=3

# POWER MANAGEMENT FOR EVERY USED AHCI CHANNEL (ahcich 0-3)
  hint.ahcich.0.pm_level=5
  hint.ahcich.1.pm_level=5
  hint.ahcich.2.pm_level=5
  hint.ahcich.3.pm_level=5

# MAX SEND QUEUE SIZE
  net.link.ifqmaxlen=2048

# DISABLE USB PACKET FILTERING
  hw.usb.no_pf=1

# NO USB DEVICE ENUMERATE WAITING AT BOOT AND SHUTDOWN
  hw.usb.no_boot_wait=1
  hw.usb.no_shutdown_wait=1 

# DISABLE hwpstate_intel(4) DRIVER
  hint.hwpstate_intel.0.disabled=1

/etc/rc.conf

Now the main FreeBSD /etc/rc.conf configuration file.

# SILENCE
  rc_startmsgs=NO
  rc_info=NO

# NETWORK
  hostname=minimal
  defaultroute_delay=3
  defaultroute_carrier_delay=3
  ifconfig_vtnet0="inet 10.1.1.71/24 up"
  defaultrouter="10.1.1.1"
  gateway_enable=YES
  harvest_mask=351
  rtsol_flags="-i"
  rtsold_flags="-a -i"

# POWER
  performance_cx_lowest=C1
  economy_cx_lowest=Cmax

# DAEMONS
  update_motd=NO
  local_unbound_enable="NO"
  dbus_enable=YES
  syslogd_flags='-s -s'
  sendmail_enable=NO
  sendmail_submit_enable=YES
  sendmail_outbound_enable=NO
  sendmail_msp_queue_enable=NO

# FS
  fsck_y_enable=YES
  clear_tmp_enable=NO
  clear_tmp_X=YES

# OTHER
  keyrate=fast
  virecover_enable=NO
  devfs_system_ruleset=desktop
  entropy_file=NO
  savecore_enable=NO
  dumpdev=AUTO

/etc/sysctl.conf

Now FreeBSD system settings in the /etc/sysctl.conf file.

# HARVEST MASK FOR random(4)
  kern.random.harvest.mask=33119

# SECURITY
  security.bsd.see_jail_proc=0
  security.bsd.unprivileged_proc_debug=0

# SECURITY/RANDOM PID
  kern.randompid=1

# DISABLE ANNOYING THINGS
  vfs.usermount=1
  kern.coredump=0
  hw.syscons.bell=0
  kern.vt.enable_bell=0

# DO NOT WAIT FOR USB DEVICES ON SUSPEND/SHUTDOWN
  hw.usb.no_suspend_wait=1
  hw.usb.no_shutdown_wait=1

# DESKTOP/INTERACTIVITY
  kern.sched.preempt_thresh=224

# DESKTOP QUANTUM FOR TIMESHARE THREADS IN stathz TICKS
  kern.sched.slice=3

# DESKTOP/IRIDIUM/CHROMIUM
  kern.ipc.shm_allow_removed=1

# ALLOW idprio(8) USE BY REGULAR USER
  security.bsd.unprivileged_idprio=1

# PREVENT SHARED MEMORY FROM BEING SWAPPED TO DISK
  kern.ipc.shm_use_phys=1

# DO NOT SWITCH VIRTUAL CONSOLES BACK AND FORTH ON SUSPEND
  kern.vt.suspendswitch=0

# MAKE FUSEFS DO NOT USE WIRED MEMORY
  vfs.fusefs.data_cache_mode=0

/etc/devfs.rules

The devfs_system_ruleset specified desktop in the /etc/devfs.rules file.

[desktop=10]
add path 'acd*'      mode 0660 group operator
add path 'cd*'       mode 0660 group operator
add path 'da*'       mode 0660 group operator
add path 'pass*'     mode 0660 group operator
add path 'xpt*'      mode 0660 group operator
add path 'fd*'       mode 0660 group operator
add path 'md*'       mode 0660 group operator
add path 'uscanner*' mode 0660 group operator
add path 'ugen*'     mode 0660 group operator
add path 'usb/*'     mode 0660 group operator
add path 'video*'    mode 0660 group operator
add path 'cuse*'     mode 0660 group operator

Installed Packages

Only a few … with few hundred dependencies 🙂

FreeBSD # pkg install xlibre openbox tint2 dzen2 xterm htop ifstat doas \
                      gnome-icons-faenza adwaita-icon-theme mate-icon-theme

What I really loved is that XLibre X11 packages DOES NOT CONFLICT with Xorg packages. You just install xlibre instead of xorg and everything works … even better then with Xorg 🙂

Login Manager

I did not used login manager such as xdm(1) as its not needed in the setup.

I just start X11 directly with xinit(1) command like that.

FreeBSD % xinit -- -dpi 75 -nolisten tcp

If you would like to add xdm(1) to the mix then it would add additional 12 MB to RAM usage.

FreeBSD # ps aux -o user,rss,command | grep -e xdm -e RSS | cut -c 59-
USER           RSS COMMAND
root          8824 xdm: :0 (xdm)
root          4596 /usr/local/bin/xdm -server :0 local /usr/local/bin/X :0  vt05

~/.xinitrc

Now the details what is being set and started for this minimalistic yet powerful desktop.

# PATH
  export PATH=${PATH}:~/scripts

# SET PROPER locale(1)
  export LC_ALL=en_US.UTF-8
  export   LANG=en_US.UTF-8

# fontconfig
  export FREETYPE_PROPERTIES="cff:no-stem-darkening=0 autofitter:no-stem-darkening=0"

# MODIFY QT FONT DPI
  export QT_FONT_DPI=75

# DISABLE OVERLAY SCROLLBARS
  export GTK_OVERLAY_SCROLLING=0

# XDG
  export DESKTOP_SESSION=openbox
  export XDG_SESSION_DESKTOP=openbox
  export XDG_CURRENT_DESKTOP=openbox
  export XDG_SESSION_CLASS=user
  export XDG_SESSION_TYPE=x11

# DISABLE GVFS FUSE ~/.gvfs MOUNT
  export GVFS_DISABLE_FUSE=1

# QT MUST KNOW WHERE IS GTK2 CONFIG
  export GTK2_RC_FILES="${HOME}/.gtkrc-2.0"

# QT5 qt5ct
  export QT_QPA_PLATFORMTHEME=qt5ct

# GTK/QT ANTIALIASING
  export QT_XFT=1
  export GDK_USE_XFT=1

# FORCE LIBREOFFICE TO USE GTK2 THEME
  export OOO_FORCE_DESKTOP=gnome

# WM
  exec dbus-launch --exit-with-session openbox-session 1> /dev/null 2> /dev/null & WM=${!}

# DAEMONS/TOOLS/TASKBARS/BACKGROUND
  ( sleep 1 && ~/scripts/__openbox_restart_dzen2.sh 1> /dev/null 2> /dev/null ) &
  ( sleep 1 && ~/scripts/__openbox_restart_tint2.sh 1> /dev/null 2> /dev/null ) &
  xbindkeys                                         1> /dev/null 2> /dev/null   &
  setxkbmap -option terminate:ctrl_alt_bksp,caps:none pl                        &
  ( sleep 5 && xmodmap ~/.xmodmaprc )                                           & 

# WAIT FOR openbox(1) WM PID
  wait ${WM}

# LOGOUT WHEN X11 STARTED FROM PLAIN login(1) CONSOLE
  XINIT=$( ps -o pid,comm | awk '/xinit/ {print $1}' )
  SHELL=$( ps -o ppid -p ${XINIT} | grep -v PPID )
  LOGIN=$( ps -o ppid -p ${SHELL} | grep -v PPID )
  kill -9 ${XINIT} ${SHELL} ${LOGIN} 2> /dev/null

# EXIT
  exit 0


For the record … this section at the end makes sure that after X11 will end its process my user will be securely and automatically logged out.

# LOGOUT WHEN X11 STARTED FROM PLAIN login(1) CONSOLE
  XINIT=$( ps -o pid,comm | awk '/xinit/ {print $1}' )
  SHELL=$( ps -o ppid -p ${XINIT} | grep -v PPID )
  LOGIN=$( ps -o ppid -p ${SHELL} | grep -v PPID )
  kill -9 ${XINIT} ${SHELL} ${LOGIN} 2> /dev/null

Startup

This is how the system looks after its booted.

After executing the xinit -- -dpi 75 -nolisten tcp command Openbox window manager awaits our commands with Tint2 and Dzen2 bars on the top.

The kld.sh script converts FreeBSD kernel (and its modules) RAM usage display into MB units and its talked in depth in the Part 6 – Learn Shell Scripting of the Ghost in the Shell series.

RAM Usage

After starting xterm(1) terminal and then htop(1) inside to measure RAM usage the number stops at 230 MB … but as we started these only to measure the usage the real RAM usage of such FreeBSD desktop without any applications is 206 MB RAM.

I subtracted:

– 19 MB for xterm(1) terminal.

– 5 MB for htop(1) process viewer.

Math.

230 - 19 - 5 = 206

As calculated in the terminal.

End Session

After stopping X11 server this is how console looks like (and safely logged out).

I was also positively surprised how cleanly and without any errors Xlibre servers ends its work.

Comparison

You can compare these 200 MB RAM to other desktop environments and window managers in one of my older articles – Desktop Environments Resource Usage Comparison – here.

Summary

As I used GENERIC FreeBSD kernel its possible to use even smaller amount of RAM with kernel recompilation.

UPDATE 1 – Hard 220 MB Limit

The tests I have done above were done on a FreeBSD Bhyve virtual machine with 6 GB RAM. That means plenty of space for buffers and cache – and the FreeBSD motto is that – “Free memory is wasted memory.” – I decided to try with smallest VM I can start in UEFI mode.

That means 220 MB of RAM.

The results I got surprised me more then I expected.

Plain FreeBSD

When VM had 6 GB RAM plain FreeBSD used about 115 MB RAM – but when I limited the physical memory to 220 MB RAM for that virtual machine only 82 MB RAM were used.

Openbox

Here the results are also better.

My complete Openbox/Tint2/Dzen2 desktop uses only 134 MB RAM!

The calculations are: 142 (ram) + 14 (swap) – 18 (xterm) – 4 (htop)

Hope that helps.

EOF