灵符lingfu

LingSys

↓ 0 downloads

Your machine's memory, GPU, motherboard and network, drawn and played in the Ling design system: LingSys, a small build for USB liquid-cooler displays, LingNet for IPv4/IPv6, DNS and packets, and a LingOS edition. 64-bit and 32-bit Windows builds included.

Keywords system-monitor, visualization, network, ipv6, gpu, lcd, lingos, ling
lingfu install LingSys
LicenseMIT
AuthorsLing Lin <taellinglin@gmail.com>
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

README

HatchSYS (HatchMEM)

Your machine, drawn and played in the Ling design system: a main screen with the system's vital signs, and a menu that opens four sections, Memory, GPU, Board (motherboard and CPU) and Network. Written in Ling (no Rust).

Circles are things coming in (a page read, a packet received, a frame drawn). Squares are things going out (a page written, a packet sent, a copy). Every section has seven channels that take the seven Ling hues, and the same numbers drive an additive synth.

Run

.\run.ps1            live data from this machine (starts four samplers, stops them on exit)
.\run.ps1 sim        no samplers; a made-up machine (16 GB, four GPUs, 16 cores)
.\run.ps1 full       borderless fullscreen
.\run.ps1 memonly    the original single-screen HatchMEM (hatchmem.ling)

or ling run --interp hatchsys.ling [sim] [full] [shot] by hand, in this folder, after starting the samplers yourself.

Executables, 64-bit and 32-bit

python tools/build_exe.py                 LingSys, LingSysMini and LingNet for 64-bit (dist\x64) and 32-bit (dist\x86) Windows
python tools/build_exe.py net --x86       one app, one architecture
python tools/make_icons.py                redraw the icons (assets\*.ico) before building

The built programs are also in releases/ (with SHA256SUMS.txt): windows-x64, windows-x86 and lingos. Double-click an exe, or run LingSysMini.exe 240x320, LingSys.exe full, LingNet.exe sim. Each is self-contained (14 to 17 MB): it carries the samplers, writes them to %LOCALAPPDATA%\LingSys, starts them hidden, and stops them when you close it. If the exe is killed instead of closed, the samplers notice within a second or two and exit on their own. Nothing else needs to sit next to it. Each exe has its own icon: the rings for LingSys and LingSysMini, a constellation for LingNet (icon.svg, icon_net.svg).

The exes run on the interpreter, not on ling build's default JIT, because the JIT's memory leak (see below) would fill your RAM within minutes; that is why tools/build_exe.py exists instead of a plain ling build. The first build of each architecture compiles Ling itself and takes about six minutes, later runs about two. The exes are unsigned and start hidden PowerShell windows, so Windows SmartScreen or an antivirus may query them.

32-bit. Ling builds for 32-bit Windows with two workarounds, both done by the build script and neither touching the Ling source: one lint is allowed (a window-style constant that wraps to exactly the intended 32-bit value), and the finished exe has its import of SetWindowLongPtrW renamed to SetWindowLongW. The first is a literal rustc rejects on 32-bit; the second is because user32.dll on 32-bit Windows has no export with the Ptr name (it is a header macro there), so an unpatched exe stops in the Windows loader with an "entry point not found" error. The proper fix is in Ling's src/runtime/mod.rs. I ran the 32-bit exes on 64-bit Windows (window, samplers, live data, flat memory); I have not run them on a 32-bit installation.

LingOS

ling build lingos/hatchsys_os.ling --platform lingos --out dist/lingos      ->  dist/lingos/apps/hatchsys_os.elf

The monitoring programs cannot run on LingOS: its userland (crates/ling-user) has print, math, lists, strings, a framebuffer (plot, plot_disc, clear), key polling and a clock, and no windows, files, performance counters or network stack. (Building hatchmini.ling for LingOS compiles to native code and then fails to link on ling_list_set, and would have no way to draw or read anything anyway.) lingos/hatchsys_os.ling is a small LingOS-native edition instead: the Rings view, seven hue rings with crosshatched arcs turning against each other, drawn straight to the framebuffer and moved by a synthetic activity signal. Press any key to quit. Where it computes act, real counters can go in when LingOS has them. It builds and links to a valid 64-bit x86-64 ELF (37 KB); I have not run it on LingOS.

Keys and mouse

InputDoes
0 / 1 2 3 4Main / Memory / GPU / Board / Network
Left Rightprevious / next section
Tab or Spacenext view in the section (on Main: next section)
Up Downpick the GPU (GPU section, when you have more than one); in the Fleet view you can also click a card
Aauto-cycle through every view, 28 s each
Hhide the HUD text (the menu stays)
Ppluck mode: clicks and ticks instead of hums and chimes
Nalerts on / off
Mmute
Escback to Main; on Main, quit
Qquit
clickthe menu along the bottom (sections, then the views of the current section); on Main, click a card to open its section

shot saves one PNG per view (15 of them) into screenshots/ and quits.

Small version for a liquid-cooler display

.\run.ps1 mini 320x240      (or 240x320, 480x480, any WxH; 320x240 is the default)

hatchmini.ling is a cut-down build for a small screen: four rings (memory, GPU, CPU, network), four stat rows with the number you actually want to read, a heat reading in the hub, and the same alert banner. No menu and no sound. It uses the same samplers and the same design system. In landscape the rings are on the left and the rows down the right; in portrait the rings are on top with the rows in a 2 x 2 grid.

On a USB liquid-cooler display

.\run.ps1 lcd                  hatchmini on the display (add rotate=270 or rotate=180 if it is sideways or upside down)
python tools/lcd_sender.py --test    send a test card: colour bars and an arrow that should point to the top of the display

This drives displays that identify as USB 0416:5302 ("USBDISPLAY", the Thermalright LCD family that TRCC controls). Ling can only open an ordinary window, so the tool, tools/lcd_sender.py, mirrors the hatchmini window: it captures the window (even when other windows cover it), turns it, JPEG-encodes it, and sends it over USB about ten times a second. run.ps1 lcd starts the samplers, the mini window and the tool together, and stops them all when you close the mini window.

Close TRCC first. Only one program can own the display, so run.ps1 lcd closes TRCC and its USB helpers, then restarts TRCC when you are done (if it was running). If you use the tool by hand, close TRCC yourself. You need pip install pyusb libusb-package pillow.

How it works, so you can check it: the packet format is the one TRCC's own USB helper (USBLCDNEW) sends, read out of TRCC's code. The tool does the same handshake, which makes the display reply with a panel code and serial number; then, for every frame, a 20-byte header (DA DB DC DD, picture command, width, height, JPEG format, JPEG length) followed by the JPEG, in 512-byte chunks to endpoint 2. Your display answered the handshake as panel code 58, which TRCC treats as a 240 x 320 portrait panel and feeds by turning its 320 x 240 pictures a quarter turn, which is what --rotate 90 (the default) does.

What I verified and what I could not: the handshake succeeds, the test card and live frames go out without a USB error, and the frames saved from the tool show hatchmini correctly. I cannot see the display, so the orientation (and whether it looks sharp) is for you to confirm; if the picture is turned, change rotate=. Only code 58 has been tried; the tool also knows the packet sizes for codes 54, 72, 128 and 129 from TRCC's code, and uses 240 x 320 for anything else. Frame rate is limited by the interpreter and the USB link, so expect roughly 8 to 10 frames a second.

LingNet: the network in detail

.\run.ps1 net          (or dist\LingNet.exe; build it with python tools/build_exe.py net)

A separate program for the network alone, with IPv4 and IPv6, DNS, packets and addresses, and everything split by device, meaning each network adapter on this PC (Wi-Fi, Ethernet, a VPN, the WSL and VirtualBox adapters...). Keys: Tab / Left / Right or 1-6 change view, Up / Down pick the device (ALL, then each adapter), H hides the status line, Q quits. The bar along the bottom is clickable: views on the left, device chips on the right; on DEVICES you can also click a card. Optional size and flags: LingNet.exe 1000x600, full, sim.

ViewWhat it shows
DevicesOne card per adapter: link speed, bytes in and out, packets, multicast, errors, its first IPv4 and IPv6 address with scope, gateways, its connection count split IPv4 / IPv6, its neighbour count, and a minute of history.
FlowThe connections of the chosen device in sectors by remote port; circle = IPv4, diamond = IPv6; pulses at your real in and out rates. The busiest processes on the right.
PacketsSeven lanes for the chosen device: bytes in and out, packets in and out, multicast in and out, errors and discards.
ProtocolsSeven rings: IPv4, IPv6, TCP over each, UDP over each, ICMP (both). The hub is IPv6's share of IP traffic. Connection states for each IP version on either side. Windows counts these per protocol, not per adapter, so this view always covers all devices.
DNSEach device's DNS servers with the latency Windows would get from them (probed directly, IPv4 and IPv6 servers alike), whether AAAA records are answered, and the local DNS cache broken down by record type (A, AAAA, CNAME, PTR, SRV, other, negative).
AddressesFor each device: every IPv4 and IPv6 address with prefix, scope (global, private, ULA, link-local, CGNAT) and origin (DHCP, router advertisement, static), gateways, DNS servers, MTU, DHCP. On the right, the neighbours the device can see (ARP for IPv4 on the outer ring, NDP for IPv6 on the inner one), coloured reachable, stale or unanswered.

What "by device" can and cannot mean: Windows keeps traffic counters per adapter, and its connection table names the local address each connection uses, so bytes, packets and connections can be split by adapter. It does not count traffic for the other machines on your network; the neighbour table shows who is there, not how much they send. Protocol counters (IPv4 against IPv6, TCP, UDP, ICMP) are system-wide.

Privacy: your own addresses are shown, since they are yours. Remote addresses, neighbour addresses and MACs, and the names in your DNS cache are never drawn or written as text; the sampler writes only counts, ports, process names and hashes. The DNS probe sends one small query per configured DNS server, every eight passes or so, for dns.msftncsi.com (the name Windows itself uses to check connectivity), straight to that server, so your own cache does not answer it and nothing is added to it.

Honest notes: on this machine IPv6 is link-local only, so the global and ULA scopes (and the IPv6 DNS servers) are exercised only by sim; I have not seen them with live data. The detailed sampler takes up to several seconds on the passes that refresh addresses, neighbours and DNS, so LingNet only calls its data stale after 20 seconds. The ring views (Protocols, DNS) run at about 8 fps on the interpreter.

Main

Four Chesilin rings (memory, GPU, CPU, network) around the uptime, and a card for each section with its headline numbers, a usage bar and the last minute as a trace. Each card carries a LIVE, STALE or SIM tag for its data.

Sections and views

SectionViewWhat it shows
MemoryRingsOne ring per memory category, an arc of crosshatch for its share of RAM.
TilesA 32 x 32 page map along a Hilbert curve (each cell is 1/1024 of RAM), with a Daemon tile legend.
OrbitsThe 22 biggest processes. Circle = working set, inscribed square = private bytes, orbit speed follows I/O.
WeaveSeven strings at the pitch and loudness the synth uses; every read and write is a note.
GPUEnginesSeven rings: 3D, compute, copy, decode, encode, VRAM, power. The hub is the card's utilisation.
VRAMA 1024-cell map of the card's memory; the six biggest processes get a hue each, the rest is violet, free cells are dark. Pulses leave the process that did the work.
DialsUtilisation, temperature, power, core clock; a minute of history under each; memory clock, fan, PCIe link, throttle reason, driver.
FleetEvery GPU at once, one card each: a utilisation dial, VRAM, power and temperature bars, and a minute of utilisation. The selected GPU has bright corners; click a card to select it. Up to eight GPUs.
BoardLayoutA schematic of the board: CPU socket with one square per logical processor, memory slots (the ones your DIMMs sit in are hatched, with size and speed), PCIe slots with your GPUs in them, an M.2 slot, the chipset, SATA ports, rear I/O. Pulses run along the buses. Beside it: board, BIOS, CPU, memory, uptime, interrupt / DPC / context-switch rates, per-disk throughput and busy time.
CoresEvery logical processor as a body on a ring: circle = clock speed, square = load, hue runs round the ring.
SignalsSeven lanes: CPU load, ACPI temperature, interrupts, DPCs, context switches, disk read, disk write, with the last minute of each.
NetworkFlowA constellation: each live TCP connection is a dot, in a sector for its remote port (HTTPS, HTTP, DNS, REMOTE, MAIL, HIGH, OTHER). Receive pulses are circles travelling in, sends are squares travelling out. Link facts on the left, the processes holding the most connections on the right.
LinksSeven rings: receive, transmit, packets in and out, TCP, UDP, retransmits. The hub is your gateway latency.
TracesSeven lanes with the last minute of each.

Daemon and Chesilin are the design system's own scripts, so labels are not Latin letters. In Memory the category order and hues are the same everywhere:

HueLing keyCategorySource
redasmKERNELpaged + non-paged pool
orangelitSTANDBYcached, reclaimable pages
yellowbindDATAprivate working sets of all processes
greenctlMODIFIEDpages waiting to be written to disk
bluecallMAPPEDin use but not kernel, private or compressed
indigofnCOMPRESSEDthe Memory Compression store
violetmodFREEfree and zeroed pages

Where the numbers come from

Ling has no builtin that reads operating-system or hardware state, so PowerShell samplers write small text files about once a second and the program reads them. They read the same performance counters Task Manager shows. They never touch process memory.

FileSamplerReads
mem.snapsampler.ps1memory performance counters
gpu.snapsampler_hw.ps1 -Kind gpunvidia-smi for the card (temperature, fan, power, clocks, utilisation, VRAM, PCIe link, throttle), Windows GPU Engine / GPU Process Memory counters for engines and per-process VRAM
board.snapsampler_hw.ps1 -Kind boardSMBIOS (board, BIOS, memory modules, disks), per-processor counters (load, clock, interrupts, DPCs), system counters, disk counters, the ACPI thermal zone
net.snapsampler_hw.ps1 -Kind netinterface and TCP/UDP counters, netstat -ano, and one latency probe
netx.snapsampler_hw.ps1 -Kind netxLingNet only: per-adapter counters, IPv4 and IPv6 protocol counters, addresses, gateways, DNS servers and cache counts, neighbour tables, connections by local adapter, direct DNS probes

The file formats are documented at the top of each sampler. If a sampler stops, its section shows STALE after eight seconds and freezes on the last reading. If a sampler has produced nothing (no nvidia-smi and no GPU counters, say), that section shows made-up data tagged SIM.

Several GPUs

Engines, VRAM and Dials show one GPU at a time, the selected one (Up / Down, or a click in Fleet; the HUD says GPU 1 OF 2). Fleet shows all of them. The main screen's GPU card lists every card, and the Board layout puts the first three in PCIe slots. Alerts watch every GPU, not just the selected one. NVIDIA cards come first; any other adapter that is really in use (more than 64 MB of VRAM, such as an Intel or AMD card) gets a card of its own with engines and VRAM from the Windows counters, but no temperature, fan, power or clocks.

Things to know

  • No CPU package temperature, fan speeds or voltages. Windows does not expose them without a kernel driver. The Board views show the ACPI thermal zone, which on many desktops is a fixed, board-level value. If LibreHardwareMonitor or OpenHardwareMonitor is running, the sampler also reads its WMI sensors and the Layout view lists the first five. That path is written but I could not test it here (neither is installed).
  • GPU matching. Windows names GPUs by LUID, nvidia-smi by index. The sampler pairs them by comparing VRAM in use, which is right when your cards use clearly different amounts and can swap engine and process numbers between two cards that use almost the same. Per-process VRAM can add up to more than the card reports; the VRAM view scales it down to fit. Only NVIDIA cards get temperature, fan, power and clocks; other cards still get engines and VRAM from the Windows counters.
  • Gateway latency. Many routers ignore ping, so when ICMP gets no answer the sampler times a TCP connect (accepted or refused) to the gateway instead. Nothing leaves your network.
  • Remote addresses are never drawn as text. A connection's place in the constellation comes from a hash of its address and its remote port. netstat gives no per-connection traffic, so which dot a pulse leaves is random; the number and speed of pulses follow your real receive and send rates.
  • Memory leak on the JIT. In Ling 2030.1.48 the default JIT backend never frees heap values (list literals, list_push, string building, indexing into nested lists), so any program that builds lists every frame grows without limit: this one, and the original HatchMEM, by about 3 GB a minute, until the machine runs out of memory (it took about 15 minutes to reach 38 GB). Pure arithmetic does not leak. The tree-walking interpreter (--interp) frees memory correctly and stays flat, at roughly 20 fps instead of 60, so run.ps1 uses it by default and jit is opt-in for short sessions. If you run ling run yourself, pass --interp.
  • Windows only for live data. sim works anywhere Ling does.
  • The page map and the board layout are drawn from real totals and your real hardware inventory; they do not show physical addresses or the actual trace routing of your board. Which memory slots are hatched assumes the usual two-DIMM convention (A2 and B2 first).

What moves

  • Rotation of every ring and map follows the current section's activity; hue drifts with the outgoing side (up) and incoming side (down); saturation rises with how full the section is (RAM used, VRAM used, CPU load, link use).
  • A channel's lightness and hatch density rise with its recent activity.
  • Pulses are placed by channel weights and, where it makes sense, by body: the process that did the I/O (Memory, GPU), the core that was busy (Board), the connection (Network). Allocations are circles in the section's allocation channel (FREE, VRAM, CHIPSET, TCP).

Sound

32 audio_tone slots: 7 channels x 4 harmonics (28), plus 4 shimmer partials that open with the section's activity. The root rises from 55 Hz toward 81 Hz as the section fills. Each channel sits on a fixed ratio above it (1, 3/2, 2, 9/4, 3, 15/4, 9/2), loudness follows its share, LFO speed and depth follow its activity, and each is placed round the listener. Every pulse also fires a short chime (sine for in, triangle for out), at most 3 per frame and 14 per second. Pluck mode (P) swaps that for something percussive: the hum is switched off, and each pulse is a noise click on the attack followed by a short p

← Back to index