diff --git a/assets/sai.css b/assets/sai.css
index 793e832..fc433c8 100644
--- a/assets/sai.css
+++ b/assets/sai.css
@@ -749,13 +749,15 @@ img.branch {
transition: height 0.2s ease-out; /* Smoothly animate height changes */
}
-.inst_idle {
- /* An idle instance can have a subtle border or effect if desired */
+.inst_idle {
border-color: #555;
+ opacity: 0.5; /* Make idle instances semi-transparent */
+ transition: opacity 0.3s; /* Smoothly fade in/out */
}
.inst_busy {
- /* A busy instance can have a brighter border */
border-color: #999;
+ opacity: 1.0; /* Ensure busy instances are fully opaque */
+ transition: opacity 0.3s;
}
diff --git a/assets/sai.js b/assets/sai.js
index 1786fba..949eb57 100644
--- a/assets/sai.js
+++ b/assets/sai.js
@@ -1537,13 +1537,27 @@ function ws_open_sai()
// The bar is always the first (and only) child of the inst_box div.
const bar = instanceDiv.firstChild;
if (bar && bar.classList.contains("inst_bar")) {
- let cpu_percentage = (instanceLoad.cpu_percent / 1000) * 100;
- if (cpu_percentage > 100) cpu_percentage = 100;
+ // cpu_percent is in tenths of a percent, relative to ONE core.
+ // So 1000 = 100% = 1 full core.
+ let total_cpu_capacity = jso.core_count * 1000;
- // Let's add a minimum height so even a tiny load is visible
+ // Normalize the load to be a percentage of the ENTIRE system's capacity
+ let cpu_percentage = (instanceLoad.cpu_percent / total_cpu_capacity) * 100;
+
+ if (cpu_percentage > 100) cpu_percentage = 100;
+ if (cpu_percentage < 0) cpu_percentage = 0;
if (cpu_percentage > 0 && cpu_percentage < 1) cpu_percentage = 1;
bar.style.height = `${cpu_percentage}%`;
+
+ // Update the class for idle/busy state
+ if (instanceLoad.state) { // state == 1 means busy
+ instanceDiv.classList.add("inst_busy");
+ instanceDiv.classList.remove("inst_idle");
+ } else { // state == 0 means idle
+ instanceDiv.classList.add("inst_idle");
+ instanceDiv.classList.remove("inst_busy");
+ }
} else {
// This console log will tell us if the bar element is missing
console.error("Could not find .inst_bar child in .inst_box for", instanceDiv);
diff --git a/src/builder/b-comms.c b/src/builder/b-comms.c
index 0ebf7d7..aac38f5 100644
--- a/src/builder/b-comms.c
+++ b/src/builder/b-comms.c
@@ -600,6 +600,7 @@ saib_sul_load_report_cb(struct lws_sorted_usec_list *sul)
* under one name.
*/
lws_strncpy(lr->builder_name, builder.host, sizeof(lr->builder_name));
+ lr->core_count = saib_get_cpu_count();
int system_load = saib_get_system_cpu(&builder);
diff --git a/src/builder/b-load.c b/src/builder/b-load.c
index 2074661..bdf3a4e 100644
--- a/src/builder/b-load.c
+++ b/src/builder/b-load.c
@@ -27,6 +27,29 @@
#include <mach/mach_host.h>
#endif
+#if defined(WIN32)
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+int
+saib_get_cpu_count(void)
+{
+ long nprocs = -1;
+#if defined(WIN32)
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ nprocs = sysinfo.dwNumberOfProcessors;
+#elif defined(_SC_NPROCESSORS_ONLN)
+ nprocs = sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+ if (nprocs < 1)
+ return 1; /* Fallback */
+
+ return (int)nprocs;
+}
+
/*
* Returns CPU usage as an integer from 0-1000 (for 0.0% to 100.0%)
* or -1 on error.
diff --git a/src/builder/b-private.h b/src/builder/b-private.h
index 61255f6..fbc81f7 100644
--- a/src/builder/b-private.h
+++ b/src/builder/b-private.h
@@ -241,3 +241,5 @@ saib_get_cgroup_cpu(struct sai_nspawn *ns);
int
saib_get_system_cpu(struct sai_builder *b);
+
+int saib_get_cpu_count(void);
diff --git a/src/common/include/private.h b/src/common/include/private.h
index 387c314..e363331 100644
--- a/src/common/include/private.h
+++ b/src/common/include/private.h
@@ -77,6 +77,7 @@ typedef struct sai_platform_load {
typedef struct sai_load_report {
lws_dll2_t list; /* For queuing on sai_plat_server */
char builder_name[64];
+ int core_count;
lws_dll2_owner_t platforms; /* List of sai_platform_load_t */
} sai_load_report_t;
diff --git a/src/common/struct-metadata.c b/src/common/struct-metadata.c
index d8568b7..ff74673 100644
--- a/src/common/struct-metadata.c
+++ b/src/common/struct-metadata.c
@@ -35,6 +35,7 @@ const lws_struct_map_t lsm_platform_load[] = {
const lws_struct_map_t lsm_load_report_members[] = {
LSM_CARRAY (sai_load_report_t, builder_name, "builder_name"),
+ LSM_SIGNED (sai_load_report_t, core_count, "core_count"),
LSM_LIST (sai_load_report_t, platforms, sai_platform_load_t, list,
NULL, lsm_platform_load, "platforms"),
};