perf: faster builds, leaner daemon, smoother install/run (0.9.20)

Reuse libcstcore.a for tests with -MMD incremental deps; idle-backoff the
parliament seat loop; defer curl init and cache settings; add systemd helper.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WHC
2026-10-29 11:41:16 +08:00
co-authored by Cursor
parent 812e3ee265
commit 2f96b050d6
13 changed files with 278 additions and 103 deletions
+27 -4
View File
@@ -139,6 +139,26 @@ int cst_discover_local_put(const char *realm_fp, const char *instance_id,
arr = cJSON_CreateArray();
cJSON_AddItemToObject(root, "instances", arr);
}
time_t now = time(NULL);
const cJSON *it;
cJSON_ArrayForEach(it, arr) {
const cJSON *iid = cJSON_GetObjectItemCaseSensitive(it, "iid");
const cJSON *rid = cJSON_GetObjectItemCaseSensitive(it, "rid");
const cJSON *port = cJSON_GetObjectItemCaseSensitive(it, "port");
const cJSON *updated = cJSON_GetObjectItemCaseSensitive(it, "updated");
if (!cJSON_IsString(iid) || strcmp(iid->valuestring, instance_id) != 0)
continue;
if (cJSON_IsString(rid) && !strcmp(rid->valuestring, realm_fp) &&
cJSON_IsNumber(port) && port->valueint == peer_port &&
cJSON_IsNumber(updated) &&
now - (time_t)updated->valuedouble < 60) {
/* Same seat advertisement still fresh — skip disk rewrite. */
cJSON_Delete(root);
pthread_mutex_unlock(&local_mu);
return 0;
}
break;
}
local_remove_iid(arr, instance_id);
cJSON *row = cJSON_CreateObject();
cJSON_AddStringToObject(row, "rid", realm_fp);
@@ -146,7 +166,7 @@ int cst_discover_local_put(const char *realm_fp, const char *instance_id,
cJSON_AddStringToObject(row, "name", name ? name : "");
cJSON_AddNumberToObject(row, "port", peer_port);
cJSON_AddNumberToObject(row, "pid", (double)os_getpid());
cJSON_AddNumberToObject(row, "updated", (double)time(NULL));
cJSON_AddNumberToObject(row, "updated", (double)now);
cJSON_AddItemToArray(arr, row);
int rc = save_local(root);
cJSON_Delete(root);
@@ -283,12 +303,15 @@ static void *discover_main(void *arg) {
cst_discover_t *d = arg;
int ticks = 0;
while (!d->stop) {
if ((ticks++ % 10) == 0) {
/* ~100ms recv timeout: beacon every ~5s, rewrite local registry ~60s. */
if ((ticks % 50) == 0) {
send_beacon(d);
(void)cst_discover_local_put(d->realm_fp, d->instance_id, d->name,
d->peer_port);
if ((ticks / 50) % 12 == 0)
(void)cst_discover_local_put(d->realm_fp, d->instance_id, d->name,
d->peer_port);
ingest_local(d);
}
ticks++;
if (d->sock == DISC_BAD) {
struct timespec ts = {0, 100 * 1000 * 1000};
nanosleep(&ts, NULL);
+6 -1
View File
@@ -20,7 +20,12 @@ void cst_extensions_wait(FILE *log) {
cst_mcp_counts(&ready, &total);
if (total == 0)
return;
cst_mcp_wait_ready(30000);
/* Default 8s (was 30s); override with CST_MCP_WAIT_MS. */
const char *e = getenv("CST_MCP_WAIT_MS");
int ms = e && atoi(e) >= 0 ? atoi(e) : 8000;
if (ms > 60000)
ms = 60000;
cst_mcp_wait_ready(ms);
cst_mcp_info_t info[CST_MCP_MAX];
int n = cst_mcp_info(info, CST_MCP_MAX);
for (int i = 0; log && i < n; i++) {
+54 -36
View File
@@ -22,6 +22,21 @@
#include <unistd.h>
#endif
/* Defer libcurl init: --version / --login / parliament CLI need none of it. */
static int g_curl_ready;
static void cst_curl_ensure(void) {
if (!g_curl_ready) {
curl_global_init(CURL_GLOBAL_DEFAULT);
g_curl_ready = 1;
}
}
static void cst_curl_cleanup(void) {
if (g_curl_ready) {
curl_global_cleanup();
g_curl_ready = 0;
}
}
static void usage(const char *argv0) {
fprintf(stderr,
"Usage: %s [options] (works in the current directory)\n"
@@ -311,7 +326,6 @@ int main(int argc, char **argv) {
"1903 or later is required); non-ASCII text may break\n");
os_set_prog_path(argv[0]);
os_temp_dir_export();
curl_global_init(CURL_GLOBAL_DEFAULT);
cst_agent_config_t cfg = {0};
char cwd[4096];
@@ -532,7 +546,7 @@ int main(int argc, char **argv) {
case 'r':
if (cst_protocol_parse(optarg, &cfg.protocol) != 0) {
fprintf(stderr, "unknown protocol: %s\n", optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
break;
@@ -545,7 +559,7 @@ int main(int argc, char **argv) {
if (cst_tool_profile_parse(optarg, &cfg.tool_profile) != 0) {
fprintf(stderr, "unknown tool profile: %s (default | minimal)\n",
optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
break;
@@ -580,14 +594,14 @@ int main(int argc, char **argv) {
case 'A':
if (cst_approval_parse(optarg, &approval) != 0) {
fprintf(stderr, "bad --approval %s (ask | auto | yolo)\n", optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
break;
case 'C':
if (parse_confirm(optarg, &cfg) != 0) {
fprintf(stderr, "bad --confirm %s (shell,write,net | none)\n", optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
break;
@@ -595,7 +609,7 @@ int main(int argc, char **argv) {
if (!cst_effort_valid(optarg)) {
fprintf(stderr, "bad --effort %s (low | medium | high | max)\n",
optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
snprintf(cfg.effort, sizeof(cfg.effort), "%s", optarg);
@@ -603,21 +617,22 @@ int main(int argc, char **argv) {
case 'M':
if (!cst_mode_valid(optarg)) {
fprintf(stderr, "bad --mode %s (coding | general)\n", optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
snprintf(cfg.mode, sizeof(cfg.mode), "%s", optarg);
break;
case 'h':
usage(argv[0]);
curl_global_cleanup();
cst_curl_cleanup();
return 0;
case 0x100: {
const char *only = optarg;
if (!only && optind < argc && argv[optind][0] != '-')
only = argv[optind++];
cst_curl_ensure();
int rc = list_models(only);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
case 0x101:
@@ -626,7 +641,7 @@ int main(int argc, char **argv) {
case 0x102:
if (parse_port(optarg, &web.port) != 0) {
fprintf(stderr, "--web-port %s is not a port (0-65535)\n", optarg);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
web_mode = 1;
@@ -652,30 +667,30 @@ int main(int argc, char **argv) {
break;
case 'V':
printf("cst-agent %s\n", CST_VERSION);
curl_global_cleanup();
cst_curl_cleanup();
return 0;
default:
usage(argv[0]);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
}
if (do_migrate) {
int rc = migrate_store(cfg.workspace_root);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_realm_new) {
int rc = cst_parliament_cli_realm_new();
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_realm_pw_init) {
const char *pw = getenv("CST_REALM_PASSWORD");
int rc = cst_parliament_cli_realm_password_init(pw);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_login) {
@@ -687,17 +702,17 @@ int main(int argc, char **argv) {
iid = iidbuf;
}
int rc = cst_parliament_cli_login(pw, iid, realm_label, discover_peer_port);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_new_project) {
int rc = cst_parliament_cli_new_project(new_project_id);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_service_stop) {
int rc = cst_parliament_cli_service_stop();
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_service || do_service_fg) {
@@ -710,12 +725,12 @@ int main(int argc, char **argv) {
}
int rc = cst_parliament_cli_service(pw, iid, discover_peer_port,
do_service_fg);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_realm_enroll) {
int rc = cst_parliament_cli_realm_enroll(realm_enroll_id, realm_label);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_peer_listen) {
@@ -723,7 +738,7 @@ int main(int argc, char **argv) {
if (!iid)
iid = getenv("CST_INSTANCE_ID");
int rc = cst_parliament_cli_peer_listen(peer_listen_port, iid);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_peer_dial) {
@@ -743,13 +758,13 @@ int main(int argc, char **argv) {
}
}
int rc = cst_parliament_cli_peer_dial(host, port, iid);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
if (do_discover) {
const char *iid = parliament_instance ? parliament_instance : getenv("CST_INSTANCE_ID");
int rc = cst_parliament_cli_discover(iid, discover_peer_port, discover_wait_ms);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
@@ -778,7 +793,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "%s\n", err[0] ? err : "login required");
if (pw == pwbuf)
memset(pwbuf, 0, sizeof(pwbuf));
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
free(hand);
@@ -792,7 +807,7 @@ int main(int argc, char **argv) {
fprintf(stderr,
"password Realm active: run --login (or set "
"CST_REALM_PASSWORD) before opening the agent\n");
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
}
@@ -800,10 +815,13 @@ int main(int argc, char **argv) {
if (do_list) {
int rc = list_sessions(cfg.workspace_root);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
/* Agent / TUI / WebUI / headless need libcurl; parliament CLI above does not. */
cst_curl_ensure();
/* Explicit option > environment > last used (settings.json) > preset. */
cst_settings_t saved;
cst_settings_load(&saved);
@@ -815,7 +833,7 @@ int main(int argc, char **argv) {
prov = cst_provider_find(provider_name);
if (!prov) {
fprintf(stderr, "unknown provider: %s\n", provider_name);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
}
@@ -894,7 +912,7 @@ int main(int argc, char **argv) {
if (rc != 0 || cst_agent_store_path_for_id(cfg.workspace_root, id,
cfg.session_path,
sizeof(cfg.session_path)) != 0) {
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
cst_agent_store_set_current(cfg.workspace_root, id);
@@ -906,7 +924,7 @@ int main(int argc, char **argv) {
sizeof(id)) != 0) {
fprintf(stderr, "failed to init .agent/sessions under %s\n",
cfg.workspace_root);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
fprintf(stderr, "session %s\n", id);
@@ -914,7 +932,7 @@ int main(int argc, char **argv) {
if (do_demo) {
int rc = demo_ctl_impl(cfg.workspace_root);
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
@@ -924,7 +942,7 @@ int main(int argc, char **argv) {
if (cst_creds_prompt_console(cfg.provider, cfg.api_key,
sizeof(cfg.api_key)) != 0) {
fprintf(stderr, "no API key entered\n");
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
char dir[1024] = "the config directory";
@@ -936,7 +954,7 @@ int main(int argc, char **argv) {
dir);
/* --ask-key alone: save and exit */
if (force_ask_key && !cfg.headless && !prompt) {
curl_global_cleanup();
cst_curl_cleanup();
return 0;
}
}
@@ -945,7 +963,7 @@ int main(int argc, char **argv) {
"no API key for %s: start cst-agent once to enter it, or run "
"cst-agent --ask-key --provider %s\n",
cfg.provider, cfg.provider);
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
/* Router presets have no fixed model: take the first one the API lists
@@ -968,7 +986,7 @@ int main(int argc, char **argv) {
} else {
fprintf(stderr, "no model for %s: pass --model (%s)\n", cfg.provider,
err[0] ? err : "the API listed none");
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
}
@@ -989,7 +1007,7 @@ int main(int argc, char **argv) {
cst_agent_t *agent = cst_agent_create(&cfg);
if (!agent) {
fprintf(stderr, "failed to create agent (session path?)\n");
curl_global_cleanup();
cst_curl_cleanup();
return 1;
}
@@ -1021,6 +1039,6 @@ int main(int argc, char **argv) {
cst_agent_destroy(agent);
cst_extensions_unload();
curl_global_cleanup();
cst_curl_cleanup();
return rc;
}
+22 -12
View File
@@ -272,33 +272,43 @@ int cst_parliament_daemon_run(const char *password, const char *instance_id,
signal(SIGHUP, on_sig);
#endif
g_stop = 0;
int tick = 0;
int tick = 0, idle = 0;
while (!g_stop) {
cst_peer_session_t sess;
char herr[128];
if (cst_peer_accept((intptr_t)ls, &cert, sk, realm.pk, 500, &sess, herr,
sizeof(herr)) == 0) {
/* Accept wait backs off when idle so a quiet seat barely wakes. */
int accept_ms = idle > 20 ? 2000 : idle > 5 ? 1000 : 400;
if (cst_peer_accept((intptr_t)ls, &cert, sk, realm.pk, accept_ms, &sess,
herr, sizeof(herr)) == 0) {
sync_on_session(&sess);
cst_peer_close(&sess);
idle = 0;
} else {
idle++;
}
int push = cst_parliament_sync_pending();
tick++;
if ((push || tick % 10 == 0) && disc) {
/* Dial peers on push, or periodically (slower while idle). */
int period = idle > 20 ? 45 : idle > 5 ? 20 : 8;
if ((push || tick % period == 0) && disc) {
cst_peer_info_t peers[16];
int n = cst_discover_peers(disc, peers, 16);
for (int i = 0; i < n; i++) {
if (peers[i].port <= 0)
continue;
if (cst_peer_dial(peers[i].host, peers[i].port, &cert, sk, realm.pk,
3000, &sess, herr, sizeof(herr)) == 0) {
sync_on_session(&sess);
cst_peer_close(&sess);
if (n > 0 || push) {
for (int i = 0; i < n; i++) {
if (peers[i].port <= 0)
continue;
if (cst_peer_dial(peers[i].host, peers[i].port, &cert, sk, realm.pk,
3000, &sess, herr, sizeof(herr)) == 0) {
sync_on_session(&sess);
cst_peer_close(&sess);
idle = 0;
}
}
}
if (push)
cst_parliament_sync_ack();
}
sleep_ms(200);
/* No extra sleep: accept_ms already paced the loop. */
}
if (disc)
cst_discover_stop(disc);
+32
View File
@@ -7,6 +7,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
static int settings_path(char *out, size_t n) {
char dir[OS_PATH_MAX];
@@ -20,11 +22,32 @@ static void copy_str(char *dst, size_t n, const cJSON *v) {
snprintf(dst, n, "%s", v->valuestring);
}
static struct {
int valid;
time_t mtime;
off_t size;
cst_settings_t s;
} g_settings_cache;
static void settings_cache_invalidate(void) {
g_settings_cache.valid = 0;
g_settings_cache.mtime = 0;
g_settings_cache.size = 0;
}
int cst_settings_load(cst_settings_t *s) {
memset(s, 0, sizeof(*s));
char path[OS_PATH_MAX];
if (settings_path(path, sizeof(path)) != 0)
return -1;
struct stat st;
int have_st = stat(path, &st) == 0;
if (have_st && g_settings_cache.valid &&
g_settings_cache.mtime == st.st_mtime &&
g_settings_cache.size == st.st_size) {
*s = g_settings_cache.s;
return 0;
}
FILE *fp = fopen(path, "rb");
if (!fp)
return -1;
@@ -94,10 +117,19 @@ int cst_settings_load(cst_settings_t *s) {
s->nparams++;
}
cJSON_Delete(root);
if (!have_st)
have_st = stat(path, &st) == 0;
if (have_st) {
g_settings_cache.s = *s;
g_settings_cache.mtime = st.st_mtime;
g_settings_cache.size = st.st_size;
g_settings_cache.valid = 1;
}
return 0;
}
int cst_settings_save(const cst_settings_t *s) {
settings_cache_invalidate();
char dir[OS_PATH_MAX], path[OS_PATH_MAX], tmp[OS_PATH_MAX + 8];
if (os_config_dir(dir, sizeof(dir)) != 0 || os_mkdir_p(dir, 0700) != 0 ||
settings_path(path, sizeof(path)) != 0)