Skip to content

nzwsch/waffle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Waffle

A lightweight Go HTTP service for managing and monitoring the ZSNES (Super Nintendo emulator) process on Linux.

Quick Start

Prerequisites

  • Go 1.22+
  • ZSNES installed at /usr/bin/zsnes, or specify a custom path
  • (Optional) Flatpak with io.github.xyproto.zsnes installed for containerized operation

Run

# Default: launch ZSNES from /usr/bin/zsnes on port 8080
go run .

# Use Flatpak containerized ZSNES
go run . --use-flatpak

# Specify custom ZSNES path
go run . --zsnes-path=/opt/zsnes/zsnes

# Custom HTTP port
go run . --port=9090

# Combine flags
go run . --use-flatpak --port=9090

API

Waffle exposes four REST endpoints for process control and monitoring:

Start ZSNES

curl -X POST http://localhost:8080/zsnes/start
# Response: {"ok": true}

Stop ZSNES

curl -X POST http://localhost:8080/zsnes/stop
# Response: {"ok": true}

Check Process Status

curl http://localhost:8080/zsnes/status

Response:

{
  "running": true,
  "pid": 12345,
  "started_at": "2025-11-21T10:30:45.123456Z",
  "start_count": 5,
  "stop_count": 4
}

Fields:

  • running: Whether ZSNES is currently running
  • pid: Process ID (0 if not running)
  • started_at: Timestamp when current process started
  • start_count: Total number of Start() calls
  • stop_count: Total number of Stop() calls
  • exit_err: Error message from last process exit (if applicable)

Get Performance Metrics

curl http://localhost:8080/metrics

Response:

{
  "timestamp": "2025-11-21T10:30:50.654321Z",
  "pid": 12345,
  "cpu_percent": 45.2,
  "rss_bytes": 524288000,
  "vsz_bytes": 2147483648,
  "threads": 8
}

Fields:

  • timestamp: When metrics were collected
  • pid: Process ID being monitored
  • cpu_percent: CPU usage as percentage (0% on first call for a process)
  • rss_bytes: Resident Set Size in bytes
  • vsz_bytes: Virtual Set Size in bytes
  • threads: Number of active threads

Note: The /metrics endpoint requires ZSNES to be running and returns a 400 error if not.

Build

make build              # Cross-compile for Linux amd64

Output: ./waffle binary

Development

make fmt               # Format Go code

How It Works

Waffle provides a simple HTTP interface to lifecycle-manage ZSNES with real-time performance monitoring:

  1. Process Management: Start and stop ZSNES either as a native binary or via Flatpak containerization
  2. Status Tracking: Monitor process state, start/stop counts, and last exit errors
  3. Metrics Collection: Real-time CPU, memory, and thread metrics from Linux /proc filesystem

All state mutations are protected by mutexes for thread-safe concurrent access. The service has zero external dependencies—it uses only Go's standard library.

Implementation Details

CPU Usage Calculation

CPU percentage is calculated as: (ΔprocTicks / ΔsysTicks) × 100 × NumCPU

This approximates the behavior of tools like top across multiple CPU cores. The first metrics call for a process returns 0% due to insufficient historical data.

Memory Reporting

  • RSS (Resident Set Size): Stored as page count in /proc/[pid]/stat, converted to bytes using system page size
  • VSZ (Virtual Set Size): Stored directly in bytes

Dual-Mode Operation

Native Mode (default):

  • Launches ZSNES binary directly
  • Graceful shutdown via SIGTERM signal
  • Any non-zero exit code is treated as an error

Flatpak Mode (--use-flatpak):

  • Launches via flatpak run io.github.xyproto.zsnes
  • Termination via flatpak kill io.github.xyproto.zsnes
  • Exit code 137 / SIGKILL (from flatpak kill) is treated as normal shutdown
  • Other exit codes are treated as errors

About

A lightweight Go HTTP service to control and monitor ZSNES on Linux.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors