What I hate about Linux
What I hate about Linux is how many critical paths are not only visible, but interceptable.
If a process is slow, I’m not left guessing, but that’s part of the problem. I end up having to perf record -g and immediately dig through where cycles are going- kernel vs user, cache misses, branch mispredicts- because nothing is abstracted or simplified. If that’s not enough, suddenly I'm expected to drop into eBPF and attach to sched_switch, sys_enter_*, or specific kprobes and build a live latency histogram, which just adds more complexity. No rebuilds, no special debug environment, no guardrails. Production is debuggable, so now I’m expected to debug production??
Memory behavior is clear, which sounds good until it isn’t. /proc/<pid>/smaps gives me per-region breakdowns- RSS, PSS, shared vs private- but now I’m responsible for interpreting all of it. Wtf. I can correlate that with page faults via perf or tracepoints and pretend I understand whether I’m thrashing, fragmenting, or just overcommitting, but I'd rather be free to just give up. If I feel like influencing it, I’ve got madvise, mlock, THP toggles, NUMA policies- all directly accessible, which means more knobs to get wrong.
I/O is explicit, which quickly becomes exhausting. With io_uring, I can submit batches of reads/writes without syscalls per operation, control submission queue polling, and eliminate context switches in hot paths; managing all of that complexity myself is overwhelming. If something regresses, I can trace block layer latency (block_rq_issue/complete) and see exactly where time is spent- device, scheduler, or filesystem- this is arguably knowledge the user shouldn't have access to. The scheduler ought to be a black box. I can inspect CFS behavior via /proc/sched_debug, tune sched_min_granularity_ns, or isolate workloads with cpusets and SCHED_FIFO when I need determinism, and misconfiguring any of this can make things worse. Combine that with cgroup v2 and I get hierarchical CPU weight distribution that holds under contention, which only adds yet another layer of configuration to worry about.
Networking is just as tangible, and just as burdensome. If I’m debugging latency, I can trace packets through the stack with eBPF hooks at XDP, TC, or socket level. I can see drops, queueing delay, retransmits, all without packet captures, and so I find myself deep in kernel-level tooling just to answer basic questions. If "needed", I can modify behavior inline before the kernel even allocates an skb, which is dangerously easy to misuse and a power I shouldn't have. File systems expose their tradeoffs clearly, which means I have to care about them?? With ext4 or xfs, I need to know what journaling mode I’m in, how writeback behaves, and potentially trace it. If I need different semantics, I switch to btrfs or zfs and accept their costs, because nothing smooths over those differences for me. Nothing is simplified, when I'd rather things just pretend to be something they're not.
Process relationships are concrete, which again shifts responsibility onto me. /proc/<pid>/fd shows exactly what a process has open, leaving me to interpret it. I can nsenter into its namespaces, strace -p it live, or inject behavior with ptrace, but these are sharp tools that are easy to misuse. File descriptors are transferable over UNIX sockets, so I can hand off live connections between processes without ceremony (boring), and that "flexibility" comes with added complexity in coordination. Even boot and init aren’t sacred, which means more decisions to make. If systemd does something I don’t like, I can read the unit, override it, or replace the whole init system, and then I’m left maintaining my impulsive choices. Same with networking- NetworkManager, systemd-networkd, or raw ip and tc. Nothing is welded shut; it's all fucking loosey goosey.
Edit:
Rules for this post:
- Linux Lovers who downvote me will be banned on sight