luis's personal blog

Swaptop, monitor your swap usage in real time

Published on 12/05/2025

Post Views

You can find it at: https://github.com/luis-ota/swaptop/

Listen to Duvet - bôa while reading!

Intro

Recently I started studying Rust. It is a very cool language to understand complex concepts about computers and OS. It is considered a low-level language but it's actually very easy to learn and apply. I started the JetBrains Rust course via RustRover and learned a lot about how the language works and its syntax.

How I study and learn a new tech

After a few modules of the Rust course, I started to forget some of the initial concepts the course aborded. Normally this happens to me, so to reinforce what I learned, I created a simple project.

The problem to "solve"

Recently I started a new internship. The notebook I use there has only 8GB of RAM. Happily, I could use Linux, so I put 16GB of swap (as recommended swap = ram * 2) to avoid RAM problems, but my browser always got slow, probably because it was using only or mostly the swap.
To confirm I ran:

printf "%-8s %-20s %s\n" "PID" "NAME" "SWAP(kB)"; for pid in /proc/[0-9]*; do
  statfile="$pid/status"
  [ -r "$statfile" ] || continue
  swap=$(grep VmSwap "$statfile" | awk '{print $2}')
  [ "${swap:-0}" -gt 0 ] || continue
  name=$(grep Name "$statfile" | awk '{print $2}')
  printf "%-8s %-20s %s\n" "$(basename "$pid")" "$name" "$swap"
done | sort -k3 -nr

output

PID      NAME                 SWAP(kB)
12425    pycharm              1191416
14180    spotify              348820
23869    firefox              170060
4407     chrome               169676
32631    chrome               168028
3631     gnome-shell          162048
6007     chrome               157044
14427    chrome               152376
19347    chrome               150880
4633     chrome               137444
14026    spotify              128768
5852     chrome               123128
5736     chrome               116508
24376    Isolated             97088
34630    chrome               85236
6591     chrome               84360
4462     chrome               78020
5546     chrome               74276
13954    chrome               70612
13925    chrome               68340
4884     chrome               67424
14198    chrome               62820
4929     chrome               62228
4634     chrome               61488
...

I could confirm: Chrome was using a lot of swap. There's not much I can do about it. The point was:

To find the command to show this output was not very easy, and once I had it I saved it somewhere, and as normally, I lost it.
So I thought, is there a tool to monitor swap?
I searched for a minute and then realized, why not make one?.

Inspiration

I love TUI tools in the Linux terminal. One of my favorites is btop. Btop is a very very very pretty TUI tool to monitor hardware usage in Linux. I use it every day. But the info about swap is very simple:
btop-swap-info

So my goal was: make a btop-like tool, but for swap
......... SWAPTOP!

The Start

First I learned how Linux logs the meminfo: /proc

As in the docs: https://docs.kernel.org/filesystems/proc.html

The proc file system acts as an interface to internal data structures in 
the kernel. It can be used to obtain information about the system and to
change certain kernel parameters at runtime (sysctl).

So to get the info, I needed to learn the proc filesystem structure and read it, cluster it, etc. Yes, too complicated, or... not.

There's already a Rust lib to consume: procfs.

So the meminfo step was ok.

The Interface

As I said, I wanted it to be a TUI interface like btop, so I searched for libs in Rust to do it.

First I found tui-rs, then, ratatui, so I decided to use Ratatui...
Because, you know, Ratatui!

ratatui

So the frontend and backend tools were there, now time to get hands on.

The development

Backend

I created some structs:

For the process lines:

#[derive(Debug, Clone)]
pub struct ProcessSwapInfo {
    pub pid: i32,
    pub name: String,
    pub swap_size: f64,
}

For the chart:

#[derive(Debug, Clone, Default)]
pub struct SwapUpdate {
    pub aggregated: Vec<ProcessSwapInfo>, 
    pub total_swap: u64,
    pub used_swap: u64,
}

And then the functions:

pub fn get_processes_using_swap(unit: SizeUnits) -> Result<Vec<ProcessSwapInfo>, SwapDataError>{}

and

pub fn get_chart_info() -> Result<SwapUpdate, SwapDataError>{}

And some others for features like aggregating and changing the unit from KB, MB, GB, etc.

Interface

I started by using a Ratatui demo and went from there.

First I created a function to create the lines for the processes list and render it:

fn create_process_lines(&self, aggregated: bool) -> Vec<Line<'static>> {}

fn render_processes_list(&mut self, frame: &mut Frame, area: Rect, theme: &Theme) {}

And a function to render the chart (with a lot of help from DeepSeek...):

fn render_animated_chart(&mut self, frame: &mut Frame, area: Rect, theme: &Theme) {}

After a lot of struggle and trial and error and trying again...

It was there:
swaptop

I added some features:

KeyAction
q/EscQuit application
k/m/gSwitch units (KB/MB/GB)
aToggle aggregate mode
tCycle through themes
/uScroll up
/dScroll down
Ctrl+CForce quit
< / >Decrease / Increase interval

Then some themes:
theme-demo

voilà! Swaptop!!!!

Conclusion

This project was a lot of fun to work and learn with. I learned some new concepts about Linux and Rust language. And I must say it, I fell in love with Rust. What a beautiful and great language it is. I will continue to study and create new projects with it.

Hope you enjoyed reading this post!