skip to content
==> src/load_text.c <==
1/* load.rs text(), field by field. */
2#include "mesh/load_text.h"
3#include "mesh/abi.h"
4#include "mesh/prog_table.h"
5#include "mesh/rsfmt.h"
6
7#include <stdlib.h>
8#include <string.h>
9
10static const uint8_t *H;
11static uint32_t u(size_t o) { return (uint32_t)H[o] | (uint32_t)H[o + 1] << 8 | (uint32_t)H[o + 2] << 16 | (uint32_t)H[o + 3] << 24; }
12static uint64_t u64(size_t o) { return (uint64_t)u(o) | (uint64_t)u(o + 4) << 32; }
13static float f(size_t o) { uint32_t x = u(o); float y; memcpy(&y, &x, 4); return y; }
14
15/* `{:.p}` of an f32 when on, else "-". */
16static void opt(mesh_buf *b, bool on, float v, int p) {
17    if (on) mesh_rs_fixed(b, v, p);
18    else mesh_buf_putc(b, '-');
19}
20static void fx(mesh_buf *b, float v, int p) { mesh_rs_fixed(b, v, p); }
21
22void mesh_load_text(mesh_shared *sh, mesh_buf *out) {
23    uint8_t *hb = malloc(MESH_SNAP_HOST);
24    mesh_host_block_bytes(&sh->host, hb);
25    H = hb;
26    uint32_t flags = u(MESH_S_LOAD_FLAGS);
27    uint64_t at = u64(MESH_S_LOAD_AT_MS);
28    mesh_buf_printf(out, "load samples %u age_ms ", u(MESH_S_LOAD_SAMPLES));
29    if (at == 0) mesh_buf_putc(out, '-');
30    else {
31        uint64_t up = mesh_host_block_uptime_ms(&sh->host);
32        mesh_buf_printf(out, "%llu", (unsigned long long)(up > at ? up - at : 0));
33    }
34    mesh_buf_printf(out, " sample_us %u\n", u(MESH_S_SAMPLE_US));
35    bool g = flags & MESH_LF_GPU;
36    mesh_buf_puts(out, "gpu share ");
37    opt(out, g, f(MESH_S_GPU_SHARE), 3);
38    mesh_buf_puts(out, " share10 ");
39    opt(out, g, f(MESH_S_GPU_SHARE10), 3);
40    mesh_buf_puts(out, " slice_us ");
41    opt(out, g, f(MESH_S_GPU_SLICE_US), 0);
42    mesh_buf_puts(out, " gap_us ");
43    opt(out, g, f(MESH_S_GPU_GAP_US), 0);
44    mesh_buf_puts(out, " max_gap_us ");
45    fx(out, f(MESH_S_GPU_MAX_GAP_US), 0);
46    mesh_buf_puts(out, " gaps_s ");
47    fx(out, f(MESH_S_GPU_GAPS_S), 1);
48    mesh_buf_puts(out, " observed ");
49    fx(out, f(MESH_S_GPU_OBS), 2);
50    mesh_buf_puts(out, " inflate ");
51    opt(out, g, f(MESH_S_GPU_INFLATE), 2);
52    mesh_buf_puts(out, " queue_us ");
53    fx(out, f(MESH_S_GPU_QUEUE_US), 1);
54    mesh_buf_puts(out, " util_ext ");
55    opt(out, flags & MESH_LF_GPU_EXT, f(MESH_S_GPU_UTIL_EXT), 2);
56    mesh_buf_puts(out, "\ncpu util ");
57    fx(out, f(MESH_S_CPU_UTIL), 3);
58    mesh_buf_puts(out, " big ");
59    fx(out, f(MESH_S_CPU_BIG), 3);
60    mesh_buf_puts(out, " little ");
61    fx(out, f(MESH_S_CPU_LITTLE), 3);
62    mesh_buf_puts(out, " iowait ");
63    fx(out, f(MESH_S_CPU_IOWAIT), 3);
64    mesh_buf_printf(out, " cpus %u big %u little %u loadavg ", u(MESH_S_CPUS), u(MESH_S_CPUS_BIG), u(MESH_S_CPUS_LITTLE));
65    fx(out, f(MESH_S_LOADAVG), 2);
66    mesh_buf_putc(out, ' ');
67    fx(out, f(MESH_S_LOADAVG + 4), 2);
68    mesh_buf_putc(out, ' ');
69    fx(out, f(MESH_S_LOADAVG + 8), 2);
70    mesh_buf_puts(out, "\ncores ");
71    uint32_t n = u(MESH_S_CPUS) < MESH_MAX_CPUS ? u(MESH_S_CPUS) : MESH_MAX_CPUS;
72    for (uint32_t i = 0; i < n; i++) {
73        uint8_t cl = H[MESH_S_CORE_CLASS + i], p = H[MESH_S_CORE_UTIL + i];
74        const char *c = cl == 1 ? "B" : cl == 2 ? "L" : "?";
75        if (p == 0xff) mesh_buf_printf(out, "%s%s-", i ? " " : "", c);
76        else mesh_buf_printf(out, "%s%s%u", i ? " " : "", c, p);
77    }
78    mesh_buf_putc(out, '\n');
79    if (flags & MESH_LF_PSI) {
80        const size_t o[8] = {MESH_S_PSI_CPU, MESH_S_PSI_MEM, MESH_S_PSI_MEM_FULL, MESH_S_PSI_IO, MESH_S_PSI_IO_FULL, MESH_S_PSI_CPU10, MESH_S_PSI_MEM10, MESH_S_PSI_IO10};
81        const char *k[8] = {"psi cpu ", " mem ", " mem_full ", " io ", " io_full ", " avg10 cpu ", " mem ", " io "};
82        for (int i = 0; i < 8; i++) { mesh_buf_puts(out, k[i]); fx(out, f(o[i]), 4); }
83        mesh_buf_putc(out, '\n');
84    } else mesh_buf_puts(out, "psi -\n");
85    mesh_buf_printf(out, "mem total_mb %u avail_mb %u free ", u(MESH_S_MEM_TOTAL_MB), u(MESH_S_MEM_AVAIL_MB));
86    fx(out, f(MESH_S_MEM_FREE), 3);
87    mesh_buf_printf(out, " swap_mb %u/%u swap_out_s ", u(MESH_S_SWAP_USED_MB), u(MESH_S_SWAP_TOTAL_MB));
88    fx(out, f(MESH_S_SWAP_OUT_S), 1);
89    mesh_buf_printf(out, " compressed_mb %u level ", u(MESH_S_MEM_COMPRESSED_MB));
90    if (flags & MESH_LF_MEM_LEVEL) mesh_buf_printf(out, "%u", u(MESH_S_MEM_LEVEL));
91    else mesh_buf_putc(out, '-');
92    mesh_buf_puts(out, "\nmeshd cpu ");
93    fx(out, f(MESH_S_MESHD_CPU), 3);
94    mesh_buf_puts(out, " rss_mb ");
95    fx(out, f(MESH_S_MESHD_RSS_MB), 1);
96    mesh_buf_printf(out, " threads %u log_dropped %u\nexec cpu ", u(MESH_S_MESHD_THREADS), u(MESH_S_LOG_DROPPED));
97    fx(out, f(MESH_S_EXEC_CPU), 3);
98    mesh_buf_puts(out, " rss_mb ");
99    mesh_rs_fixed(out, (double)u64(MESH_S_EXEC_RSS) / 1048576.0, 1);
100    mesh_buf_printf(out, " wasm_lanes %u workers %u spawns %u crashes %u\n", u(MESH_S_WASM_LANES), u(MESH_S_WORKERS), u(MESH_S_WORKER_SPAWNS),
101                    u(MESH_S_WORKER_CRASHES));
102    mesh_buf_printf(out, "disk free_mb %u total_mb %u\nthermal ", u(MESH_S_DISK_FREE_MB), u(MESH_S_DISK_TOTAL_MB));
103    if (flags & MESH_LF_THERMAL) mesh_buf_puts(out, u(MESH_S_THERMAL) < MESH_THERMAL_STATES_LEN ? MESH_THERMAL_STATES[u(MESH_S_THERMAL)] : "?");
104    else mesh_buf_putc(out, '-');
105    mesh_buf_puts(out, " temp_c ");
106    opt(out, flags & MESH_LF_TEMP, f(MESH_S_TEMP_C), 1);
107    mesh_buf_putc(out, '\n');
108    for (uint32_t s = 0; s < MESH_PROG_SLOTS; s++) {
109        size_t p = mesh_pload(s);
110        uint32_t pf = u(p + MESH_PL_FLAGS);
111        if (!(pf & MESH_PLF_LOADED)) continue;
112        char name[MESH_NAME_BYTES + 1];
113        mesh_pt_name_of(sh->mb, s, name);
114        bool gg = pf & MESH_PLF_GPU, l = pf & MESH_PLF_LAT;
115        mesh_buf_printf(out, "program %s slot %u share ", name, s);
116        opt(out, gg, f(p + MESH_PL_SHARE), 3);
117        mesh_buf_puts(out, " share10 ");
118        opt(out, gg, f(p + MESH_PL_SHARE10), 3);
119        mesh_buf_puts(out, " slice_us ");
120        opt(out, gg, f(p + MESH_PL_SLICE_US), 0);
121        mesh_buf_puts(out, " gap_us ");
122        opt(out, gg, f(p + MESH_PL_GAP_US), 0);
123        mesh_buf_puts(out, " max_gap_us ");
124        fx(out, f(p + MESH_PL_MAX_GAP_US), 0);
125        mesh_buf_puts(out, " observed ");
126        fx(out, f(p + MESH_PL_OBS), 3);
127        mesh_buf_puts(out, " p50_us ");
128        opt(out, l, f(p + MESH_PL_P50_US), 1);
129        mesh_buf_puts(out, " p90_us ");
130        opt(out, l, f(p + MESH_PL_P90_US), 1);
131        mesh_buf_puts(out, " p99_us ");
132        opt(out, l, f(p + MESH_PL_P99_US), 1);
133        mesh_buf_puts(out, " max_us ");
134        opt(out, l, f(p + MESH_PL_MAX_US), 1);
135        mesh_buf_printf(out, " lat_n %u task_us ", u(p + MESH_PL_LAT_N));
136        opt(out, pf & MESH_PLF_TASK, f(p + MESH_PL_TASK_US), 1);
137        mesh_buf_puts(out, " tasks_s ");
138        fx(out, f(p + MESH_PL_TASKS_S), 1);
139        mesh_buf_puts(out, " busy ");
140        fx(out, f(p + MESH_PL_BUSY), 3);
141        mesh_buf_puts(out, " queue_us ");
142        fx(out, f(p + MESH_PL_QUEUE_US), 1);
143        if (pf & MESH_PLF_HOST) {
144            uint32_t ex = mesh_mailbox_get(sh->mb, mesh_prog_ext(s) + MESH_PX_EXEC);
145            mesh_buf_printf(out, " exec %s cpu ", ex < MESH_BACKENDS_LEN ? MESH_BACKENDS[ex] : "?");
146            fx(out, f(p + MESH_PL_CPU), 3);
147            mesh_buf_puts(out, " cpu10 ");
148            fx(out, f(p + MESH_PL_CPU10), 3);
149            mesh_buf_puts(out, " cpu_task_us ");
150            fx(out, f(p + MESH_PL_CPU_TASK_US), 1);
151            mesh_buf_printf(out, " cpu_ms %llu rss_mb ", (unsigned long long)(u64(p + MESH_PL_CPU_NS) / 1000000));
152            mesh_rs_fixed(out, (double)u64(p + MESH_PL_RSS) / 1048576.0, 1);
153            mesh_buf_printf(out, " units %u", u(p + MESH_PL_UNITS));
154        }
155        mesh_buf_putc(out, '\n');
156    }
157    free(hb);
158}