FPS optimization pipeline for headless Unity simulation

From 21 to 25 FPS: Profiling and Optimizing a Headless Unity Simulation Pipeline

A detailed technical walkthrough of profiling and optimizing a headless Unity simulation from 21 to 25 FPS — covering NVENC GPU encoding, batch camera rendering, GPU instancing, static batching, and the failed URP migration. Every measurement, every dead end, every lesson.

April 4, 2026 · 8 min · Pavel Guzenfeld
Satellite terrain and natural sky in headless Unity simulation

Natural Skies and Satellite Terrain in a Headless Unity Simulation

How I replaced flat brown terrain and solid-color sky in a headless Unity 6 Docker simulation with real satellite imagery, SRTM topography, and a custom panoramic skybox — all fully air-gapped, no runtime network dependency. Includes NVENC GPU encoding, custom shaders, and every dead end along the way.

April 4, 2026 · 12 min · Pavel Guzenfeld
DDS Content Filter String Parameters in ROS 2

Why DDS Content Filter Parameters Silently Fail for Strings in ROS 2

DDS content filter parameter substitution (%0, %1) silently fails for string fields in ROS 2 with Fast DDS. The root cause is three layers deep — the DDS SQL grammar requires quoted string literals, but no ROS 2 layer adds the quotes. Here’s how I traced it and where to fix it.

April 4, 2026 · 7 min · Pavel Guzenfeld
From Magenta to Desert: Fixing Unity Terrain in Docker

From Magenta to Desert: Fixing Cross-Platform Unity Terrain Rendering in Docker

A detailed account of fixing terrain rendering in a headless Unity 6 Docker simulation — from magenta buildings and gray streaming cameras to textured villages with working RTSP feeds. Covers cross-platform asset bundle shader mismatches, runtime material conversion, texture recovery from broken materials, and every dead end along the way.

March 27, 2026 · 12 min · Pavel Guzenfeld
Why You Should Use stableNorm() Instead of norm()

Why You Should Use stableNorm() Instead of norm(): A Lesson from Eigen Code Review

A one-word review comment on my Eigen MR revealed that hand-rolling normalization with .norm() silently breaks on extreme inputs. Eigen already had the fix — I just wasn’t using it.

March 27, 2026 · 5 min · Pavel Guzenfeld
Anatomy of Four GStreamer Shared Memory Bugs

Anatomy of Four GStreamer Shared Memory Bugs

Four bugs in GStreamer’s shmsink/shmsrc elements — a race condition, a use-after-free, a wrong-pointer dereference, and a page alignment mismatch. What they have in common, how to find them, and what they teach about writing correct GStreamer elements.

March 24, 2026 · 11 min · Pavel Guzenfeld
Why GStreamer shmsink Always Exits with Code 1

Fixing a GStreamer Bug: Why shmsink Always Exits with Code 1

A 2-line fix for a race condition in GStreamer’s shmsink that causes every pipeline using shared memory to exit with an error. How I found it, proved it, and verified the fix with sanitizers.

March 24, 2026 · 4 min · Pavel Guzenfeld
Persistent SMB Shares on Linux

Persistent SMB Shares on Linux — From Manual Mount to Automount on Access

A step-by-step guide to mounting SMB/CIFS network shares on Linux — from one-off access in a file manager to persistent fstab entries with systemd automount that connect only when needed and gracefully handle VPN disconnects.

March 24, 2026 · 7 min · Pavel Guzenfeld
Fixing O(N²) Entity Addition in ROS 2's CallbackGroup

Fixing O(N²) Entity Addition in ROS 2's CallbackGroup

How a simple erase-remove in every add_timer() call turned entity registration into a quadratic bottleneck — and the 71x speedup from moving cleanup to the right place.

March 23, 2026 · 4 min · Pavel Guzenfeld
Linux Multi-Monitor Setup with xrandr

Linux Multi-Monitor Setup — A Practical Guide to xrandr, Lid Close, and Persistent Configuration

A hands-on walkthrough of configuring multiple monitors on Linux — from identifying displays with xrandr, turning off the laptop screen, ignoring lid close, to making it all survive a reboot. Every command explained.

March 23, 2026 · 9 min · Pavel Guzenfeld