[ANN] resmon — a TUI resource monitor written in LuaJIT, compiled to a single static ELF binary

70 views
Skip to first unread message

Pacrox

unread,
Sep 2, 2026, 6:01:57 AM (2 days ago) Sep 2
to lua-l
resmon is a terminal resource monitor (CPU, RAM, per-core usage, clock
frequency, temps, GPU) I've been building in LuaJIT.

A few things that might interest this sub specifically:

- The whole app — main loop, layout, rendering — is LuaJIT, compiled with
  `luajit -b` into bytecode headers and baked directly into the C host via
  `package.preload`. End result is a single self-contained ELF binary with
  no runtime Lua/LuaJIT dependency (glibc/libm stay dynamic since LuaJIT's
  FFI needs dlsym-style resolution against a real glibc).

- All raw-mode terminal handling, /proc and sysfs reads, and process
  spawning go through LuaJIT's FFI directly — no C helper functions beyond
  a ~60-line host.c that just boots the Lua state.

- Data collection and rendering are split: "fetchers" pull from one data
  source (a proc/sysfs file, or a piped subprocess like amdgpu_top) on
  their own refresh interval and cache the result; any number of display
  "modules" can read the same cached fetch without re-fetching. Both
  fetchers and modules are plain .lua files, loaded from disk at startup
  with loadfile() — you can drop in a custom one with zero recompilation,
  same contract the built-in ones use.

Repo: https://github.com/pacrox/resmon

Feedbacks are welcome.

Martin Eden

unread,
Sep 2, 2026, 8:51:36 AM (2 days ago) Sep 2
to lu...@googlegroups.com
On 2026-09-02 11:59, Pacrox wrote:
> resmon is a terminal resource monitor (CPU, RAM, per-core usage, clock
> frequency, temps, GPU) I've been building in LuaJIT.

What's good from LuaJIT in your project?

-- Martin


Pacrox

unread,
Sep 2, 2026, 9:40:11 AM (2 days ago) Sep 2
to lua-l
Allows to build a zero-dependency executable that can be easily copied and used on remote machines and servers.

P.

Martin Eden

unread,
Sep 2, 2026, 10:42:52 AM (2 days ago) Sep 2
to lu...@googlegroups.com
On 2026-09-02 15:40, Pacrox wrote:
> Allows to build a zero-dependency executable that can be easily copied
> and used on remote machines and servers.
>
> P.

Isn't C more adequate tool for this?

-- Martin

Pacrox

unread,
Sep 2, 2026, 10:58:16 AM (2 days ago) Sep 2
to lu...@googlegroups.com
Good point.
But I don't see what appreciable performance gain would justify the added complexity pure C would need to replicate the same scripted addon hot-loading (simple and quick to implement here) and direct termios/ioctl/etc calls, which with LuaJIT don't require hand-writing a C binding for every syscall.
The goal is a tool that's both zero-dependency and easily expandable to personal monitoring and layout needs.

P.

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/06b65d4d-4666-4407-8a9c-b29ce53cc796%40disroot.org.

Martin Eden

unread,
Sep 2, 2026, 11:05:22 AM (2 days ago) Sep 2
to lu...@googlegroups.com
On 2026-09-02 16:57, Pacrox wrote:
> The goal is a tool that's both zero-dependency and easily expandable
> to personal monitoring and layout needs.

So you're offering users to run opaque executable. Which is disguised
Lua interpreter. Okay.

What's your performance margins?

-- Martin


David Given

unread,
Sep 2, 2026, 11:09:00 AM (2 days ago) Sep 2
to lua-l
I do precisely this with WordGrinder, except I'm not even using LuaJIT --- it's a straight interpreter, and the performance is fine (disclaimer: I'm currently using Luau, which is faster than Lua, but even before I did the switch performance was still fine). Doing the low-level stuff in C and the high-level stuff in Lua is perfectly acceptable for most applications.
> --
> You received this message because you are subscribed to the Google
> Groups "lua-l" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to lua-l+un...@googlegroups.com.
> To view this discussion visit
> https://groups.google.com/d/msgid/lua-l/a4032b53-5b59-46ca-b7ca-4e5e1c860ed4%40disroot.org.

Pacrox

unread,
Sep 2, 2026, 11:24:38 AM (2 days ago) Sep 2
to lu...@googlegroups.com
 I'm not "offering" anything — I wrote this as a personal tool that I'm just sharing with whoever wants to use it. Not "disguised" — it's stated clearly in the README from the title down.
The goal was low CPU load with a reasonably fast refresh rate (on the order of tenths of a second).

Real numbers, just measured: with every fetcher/module active (including the history-graph renderers, the heaviest path), resmon uses under 10ms of CPU time over a 15s window — below /proc's own 10ms tick resolution, so under 0.1% average CPU — and ~3.9MB RSS. The workload is I/O-bound (periodic /proc reads, occasional subprocess pipes) with a 30ms input-poll loop that only redraws when a fetch actually produced new data, so there's essentially no hot loop for LuaJIT vs C to matter on. Happy to share the measurement method if you want to reproduce it.

@DavidGiven hi, do you remember me? I contributed a small bit to WordGrinder, which is still my favorite word processor.
The architecture idea for resmon actually comes straight from your WordGrinder code — I found it an optimal solution from the very start, for exactly the reasons you just laid out.

P.

Martin Eden

unread,
Sep 2, 2026, 11:42:36 AM (2 days ago) Sep 2
to lu...@googlegroups.com
On 2026-09-02 17:24, Pacrox wrote:
> resmon uses under 10ms of CPU time over a 15s window — below /proc's
> own 10ms tick resolution, [...] The workload is I/O-bound [...] with a
> 30ms input-poll loop

So your framerate is capped to ~33 FPS (And your data sources framerate
is 100 FPS.)

So no matter how slow your code is, while it executes cycle in less than
30 ms its okay. You can make it faster but framerate will still be 33 FPS.

I don't think that parsing text pseudo-files in /proc and writing to
text pseudo-file stdout is computational-heavy tasks requiring
machine-code optimizations.

That's why your architecture looked a bit strange to me.

-- Martin


Pacrox

unread,
Sep 2, 2026, 12:05:34 PM (2 days ago) Sep 2
to lu...@googlegroups.com
No, much less than ~33 FPS — we're around ~3-4 FPS, ~10 FPS at most.

It's not a real-time monitor, it's a resource monitor.
The rendering itself — character-based, on a terminal — rules out the granularity needed for real-time samples anyway.
For real-time monitoring, especially of the GPU, there are better tools.

'resmon' is a low-CPU-load monitor for everyday use. It positions itself as an alternative to tools like top, htop, btop, amdgpu_top, with the idea of grouping all that information into one coherent (strictly TUI) interface that's also easy to extend.

P.

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.

Martin Eden

unread,
Sep 2, 2026, 12:29:40 PM (2 days ago) Sep 2
to lu...@googlegroups.com
On 2026-09-02 18:05, Pacrox wrote:
> No, much less than ~33 FPS — we're around ~3-4 FPS, ~10 FPS at most.
>
> It's not a real-time monitor, it's a resource monitor.
> The rendering itself — character-based, on a terminal — rules out the
> granularity needed for real-time samples anyway.
> For real-time monitoring, especially of the GPU, there are better tools.
>
> 'resmon' is a low-CPU-load monitor for everyday use. It positions
> itself as an alternative to tools like top, htop, btop, amdgpu_top,
> with the idea of grouping all that information into one coherent
> (strictly TUI) interface that's also easy to extend.
>
> P.

Then let's aim for clarity and transparency.

(For me) one thing is when package says: "bro plz do `sudo apt install
lua` and then have GREAT FUN tinkering that nice lua scripts".

Other thing when package says: "c001 h4xx0r wr0t3 d15 d3m0", and indeed
(sometimes) displays amusing ASCIIs.

And portability and self-sufficency are different things. Some nice
algorithm in pseudocode in old book may be more portable than 80 MB
self-sufficient "assembly" in C#.

-- Martin


Michael Lenaghan

unread,
Sep 2, 2026, 12:38:09 PM (2 days ago) Sep 2
to lu...@googlegroups.com
I have no idea why you feel the need to be so judgemental about something that somebody created for themselves and decided to share.

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.

Luiz Henrique de Figueiredo

unread,
Sep 2, 2026, 12:40:41 PM (2 days ago) Sep 2
to lu...@googlegroups.com
It seems now is a good time to move this discussion to private and get
back to discussing Lua. Thanks.
--lhf

Pacrox

unread,
Sep 2, 2026, 1:52:50 PM (2 days ago) Sep 2
to lu...@googlegroups.com
One of several reasons I chose to write resmon in Lua is how little C ends up being needed for full raw-mode terminal control.
LuaJIT's FFI calls termios/ioctl directly, no C wrapper required:
libc.cfmakeraw(raw)
libc.tcsetattr(STDIN, TCSANOW, raw)


For the graphs, each terminal cell is split into a 2×3 sub-grid using the Unicode "sextant" block characters, used as actual pixels — 6 addressable points per cell instead of 1.
Bars use the same trick at a coarser resolution: the "eighth block" characters (▁▂▃▄▅▆▇█) give 8 discrete fill levels per cell instead of a binary filled/empty, enough to make a bar's value readable at a glance.
Colors are plain 24-bit truecolor ANSI SGR sequences, built with a one-line string.format("\27[38;2;%d;%d;%dm", r, g, b) — no terminal library needed either.

resmon-Thumb.png

P.

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages