[Unit] Description=LED Matrix Display Service After=network-online.target Wants=network-online.target [Service] Type=simple User=root WorkingDirectory=__PROJECT_ROOT_DIR__ Environment=PYTHONDONTWRITEBYTECODE=1 # glibc gives each allocating thread its own malloc arena, up to 8 x CPU count, # and an arena that has grown is never handed back to the OS. This process runs # 9 threads on a 3-core Pi, so the ceiling is 24 arenas -- and a rig measured at # 1030 MB resident held 23 large anonymous mappings on 64 MB-aligned addresses, # 920 MB of them, while the live data it was actually holding (widest scroll # strip seen: 35,746 x 64) accounts for roughly 15 MB. That gap is arena bloat, # not leaked objects: RSS was flat across repeated sampling, not climbing. # # Capping the arenas trades a little allocator concurrency for a large amount of # resident memory on a device that has neither to spare. 2 is the usual value; # raise it if frame times regress. Environment=MALLOC_ARENA_MAX=2 ExecStart=/usr/bin/python3 __PROJECT_ROOT_DIR__/run.py # Restart=always, not on-failure: run.py exiting 0 (a clean shutdown path taken # for a reason that no longer applies, e.g. a config reload) would otherwise leave # the service stopped and the panel dark indefinitely, with systemd considering # that a successful outcome and never bringing it back. Restart=always RestartSec=10 # Memory ceiling as a share of physical RAM, so one unit file suits a 512 MB # Pi Zero 2 W and an 8 GB Pi 5 alike. This is a backstop, not a tuning knob: it # turns "the board runs out of memory, stops being able to fork, and takes sshd # and the panel down together until someone pulls the plug" into "this one # service restarts". # # NOTE: Raspberry Pi firmware boots the kernel with cgroup_disable=memory, and # systemd accepts this setting and then silently ignores it. Verify with: # grep memory /sys/fs/cgroup/cgroup.controllers # If that prints nothing, add "cgroup_enable=memory cgroup_memory=1" to # /boot/firmware/cmdline.txt (all on line 1) and reboot. first_time_install.sh # does this for you. MemoryMax=85% StandardOutput=journal StandardError=journal SyslogIdentifier=ledmatrix # Support for on-demand plugin filtering via environment variable # The environment variable LEDMATRIX_ON_DEMAND_PLUGIN can be set via: # sudo systemctl set-environment LEDMATRIX_ON_DEMAND_PLUGIN= # Or by using an EnvironmentFile (see below) # EnvironmentFile=__PROJECT_ROOT_DIR__/config/on_demand_env.conf [Install] WantedBy=multi-user.target