<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>frn.sh on Fernando Simões</title><link>https://frn.sh/</link><description>Recent content in frn.sh on Fernando Simões</description><generator>Hugo</generator><language>en-US</language><copyright>Copyright © Fernando Simões.</copyright><lastBuildDate>Wed, 09 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://frn.sh/index.xml" rel="self" type="application/rss+xml"/><item><title>Swapping a Go heap</title><link>https://frn.sh/go-heap/</link><pubDate>Wed, 09 Sep 2026 00:00:00 +0000</pubDate><guid>https://frn.sh/go-heap/</guid><description>The case:
a cgroup running two processes with memory.max set to 900 MiB. The main process is a Go program with a baseline RSS of around 32 MiB. The other, a neighboring HTTP server, uses ~400 MiB (without spikes). The Go process spikes to 500+ MiB on io.ReadAll and proto.Unmarshal, which trigger an OOM kill. I had an idea: what if I set memory.high to 700 MiB and use a swap backend so the kernel can push anonymous pages during spikes?</description></item><item><title>Swap, memory pressure and the Go GC</title><link>https://frn.sh/swap/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate><guid>https://frn.sh/swap/</guid><description>I recently ran into a problem with cgroup running two processes, with memory.max set to 900 MiB. The main process is a Go program with a baseline RSS of around 32 MiB; the other, a neighboring HTTP server, uses ~400 MiB. The problem was that, randomly through the day, the Go process would experience a massiv spike in anonymous memory, growing from 32 MiB to 500+ MiB, which triggered an OOM kill.</description></item><item><title>io_uring without readahead</title><link>https://frn.sh/io-uring/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate><guid>https://frn.sh/io-uring/</guid><description>Note: Most of this post is me having fun with something that doesn&amp;rsquo;t run in production. I wrote it for myself and mostly to play around with io_uring and some kernel features I&amp;rsquo;ve never messed with before - I/O merging and cache misses.
Someone opened a PR to implement readahead in Turso. It was a throwaway implementation, but a good excuse to measure io_uring and understand more about it.
Turso has two backends.</description></item><item><title>1993 backends on WALWrite</title><link>https://frn.sh/pgfsync/</link><pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate><guid>https://frn.sh/pgfsync/</guid><description>DRAFT
Take a look at this wait-event table:
wait_event_type | wait_event | coun ----------------+---------------+------- LWLock | WALWrite | 1193 IO | DataFileRead | 194 IO | DataFileWrite | 4 Lock | frozenid | 2 IO | WalSync | 1 1193 backends on WALWrite made no sense at all. This was a Postgres whose normal workload barely wrote anything. IOPS had exhausted a few hours earlier. Since writes seemed to be bonking the database, I needed to understand why.</description></item><item><title>Investigating 108,725 forks</title><link>https://frn.sh/tforks/</link><pubDate>Thu, 11 Dec 2025 00:00:00 +0000</pubDate><guid>https://frn.sh/tforks/</guid><description>One of the servers was hitting 90% of CPU utilization. A few containers running, no alerts. I ssh&amp;rsquo;ed and found a process with cmd bash startup.sh that had been running for 28 minutes. I straced it for a few minutes:
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 75.36 52.698676 390 134819 26094 wait4 12.27 8.583416 78 108725 fork 7.42 5.190671 5 926332 rt_sigprocmask 2.69 1.</description></item><item><title>Sigterm a D state process</title><link>https://frn.sh/sigterm/</link><pubDate>Tue, 08 Apr 2025 00:00:00 +0000</pubDate><guid>https://frn.sh/sigterm/</guid><description>A kernel mystery I hit today: load average at 12 on a 2 vCPU machine during a production incident.
Linux load average counts three things: processes running on a CPU, processes waiting in the run queue, and processes in uninterruptible sleep - D state. From the kernel source:
The global load average is an exponentially decaying average of nr_running + nr_uninterruptible. Regular sleep doesn&amp;rsquo;t count, so if load average says 12, those 12 were either running, runnable, or in D.</description></item><item><title/><link>https://frn.sh/forks-hn/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://frn.sh/forks-hn/</guid><description>Found this one on hackernews
When I was young and really didn&amp;rsquo;t understand Unix, my friend and were summer students at NBS (now NIST), and one fine afternoon we wondered what would happen if you ran fork() forever.
We didn&amp;rsquo;t know, so we wrote the program and ran it.
This was on a PDP-11/45 running v6 or v7 Unix. The printing console (some DECWriter 133 something or other) started burping and spewing stuff about fork failing and other bad things, and a minute or two later one of the folks who had &amp;lsquo;root&amp;rsquo; ran into the machine room with a panic-stricken look because the system had mostly just locked up.</description></item></channel></rss>