From dbe6eb013cc841ce11c12c98800759fb48556df8 Mon Sep 17 00:00:00 2001 From: Dushnilin Date: Sat, 5 Sep 2026 00:14:51 +0300 Subject: [PATCH] fix(perf): eliminate 50k hosts DNS rules CPU lockup, optimize UI polling & memory limits --- .../services/runtimeUiState.service.ts | 2 +- .../resources/view/tachyon/main.js | 2 +- tachyon/files/usr/lib/components/action.uc | 6 +-- tachyon/files/usr/lib/config/validator.uc | 4 +- tachyon/files/usr/lib/diagnostics/runtime.uc | 47 ++++------------- tachyon/files/usr/lib/service/ui.uc | 2 +- tachyon/files/usr/lib/singbox/generator.uc | 50 ------------------- tachyon/files/usr/lib/singbox/runtime.uc | 6 +-- 8 files changed, 21 insertions(+), 98 deletions(-) diff --git a/fe-app-tachyon/src/tachyon/services/runtimeUiState.service.ts b/fe-app-tachyon/src/tachyon/services/runtimeUiState.service.ts index 1eceb6f6..c11c1bad 100644 --- a/fe-app-tachyon/src/tachyon/services/runtimeUiState.service.ts +++ b/fe-app-tachyon/src/tachyon/services/runtimeUiState.service.ts @@ -4,7 +4,7 @@ import { logger } from './logger.service'; import { applyUiStateToStore } from './uiState.service'; const RUNTIME_UI_STATE_REFRESH_MIN_INTERVAL_MS = 500; -const RUNTIME_UI_STATE_IDLE_POLL_INTERVAL_MS = 1000; +const RUNTIME_UI_STATE_IDLE_POLL_INTERVAL_MS = 3000; const RUNTIME_UI_STATE_ACTIVE_POLL_INTERVAL_MS = 500; // A hidden tab must not keep spawning shell commands on the router every // second: back off to one request per 30s while hidden (a force refresh on diff --git a/luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js b/luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js index b3a12ca0..2abe94e7 100644 --- a/luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js +++ b/luci-app-tachyon/htdocs/luci-static/resources/view/tachyon/main.js @@ -6629,7 +6629,7 @@ function applyUiStateToStore(uiState) { // src/tachyon/services/runtimeUiState.service.ts var RUNTIME_UI_STATE_REFRESH_MIN_INTERVAL_MS = 500; -var RUNTIME_UI_STATE_IDLE_POLL_INTERVAL_MS = 1e3; +var RUNTIME_UI_STATE_IDLE_POLL_INTERVAL_MS = 3e3; var RUNTIME_UI_STATE_ACTIVE_POLL_INTERVAL_MS = 500; var RUNTIME_UI_STATE_HIDDEN_POLL_INTERVAL_MS = 3e4; var runtimeUiStateRefreshPromise = null; diff --git a/tachyon/files/usr/lib/components/action.uc b/tachyon/files/usr/lib/components/action.uc index a5f8b652..f7a78c35 100644 --- a/tachyon/files/usr/lib/components/action.uc +++ b/tachyon/files/usr/lib/components/action.uc @@ -857,7 +857,7 @@ function clear_version_caches() { function managed_sing_box_service_installed() { let data = fs.readfile("/etc/init.d/sing-box"); - return data != null && index(as_string(data), SB_MANAGED_SERVICE_MARKER) >= 0 && index(as_string(data), "GOGC") >= 0; + return data != null && index(as_string(data), SB_MANAGED_SERVICE_MARKER) >= 0 && index(as_string(data), "GOGC=\"50\"") >= 0; } function managed_sing_box_service_text() { @@ -869,7 +869,7 @@ function managed_sing_box_service_text() { "start_service() {\n" + " config_load \"sing-box\"\n" + " local enabled config_file working_directory\n" + - " local log_stderr mem_total_kb mem_limit_mb gogc scale scale_pct\n\n" + + " local log_stderr\n\n" + " config_get_bool enabled \"main\" \"enabled\" \"0\"\n" + " [ \"$enabled\" -eq \"1\" ] || return 0\n\n" + " config_get config_file \"main\" \"conffile\" \"/etc/sing-box/config.json\"\n" + @@ -881,7 +881,7 @@ function managed_sing_box_service_text() { " procd_set_param stderr \"$log_stderr\"\n" + " procd_set_param limits core=\"unlimited\"\n" + " procd_set_param limits nofile=\"1000000 1000000\"\n" + - " procd_set_param env GODEBUG=\"madvdontneed=1\"\n" + + " procd_set_param env GODEBUG=\"madvdontneed=1\" GOGC=\"50\"\n" + " procd_set_param term_timeout 15\n" + " procd_set_param respawn\n" + " procd_close_instance\n" + diff --git a/tachyon/files/usr/lib/config/validator.uc b/tachyon/files/usr/lib/config/validator.uc index 6e13a732..c6a52641 100644 --- a/tachyon/files/usr/lib/config/validator.uc +++ b/tachyon/files/usr/lib/config/validator.uc @@ -2082,7 +2082,7 @@ function managed_sing_box_service_script(marker) { "start_service() {\n" + " config_load \"sing-box\"\n" + " local enabled config_file working_directory\n" + - " local log_stderr mem_total_kb mem_limit_mb gogc scale scale_pct\n" + + " local log_stderr\n" + "\n" + " config_get_bool enabled \"main\" \"enabled\" \"0\"\n" + " [ \"$enabled\" -eq \"1\" ] || return 0\n" + @@ -2097,7 +2097,7 @@ function managed_sing_box_service_script(marker) { " procd_set_param stderr \"$log_stderr\"\n" + " procd_set_param limits core=\"unlimited\"\n" + " procd_set_param limits nofile=\"1000000 1000000\"\n" + - " procd_set_param env GODEBUG=\"madvdontneed=1\"\n" + + " procd_set_param env GODEBUG=\"madvdontneed=1\" GOGC=\"50\"\n" + " procd_set_param term_timeout 15\n" + " procd_set_param respawn\n" + " procd_close_instance\n" + diff --git a/tachyon/files/usr/lib/diagnostics/runtime.uc b/tachyon/files/usr/lib/diagnostics/runtime.uc index ce4c56bd..33766e33 100644 --- a/tachyon/files/usr/lib/diagnostics/runtime.uc +++ b/tachyon/files/usr/lib/diagnostics/runtime.uc @@ -2898,25 +2898,12 @@ function run_doctor_checks_impl(repair) { } else if (free_mb >= 0) { issues++; doc_check("⚠️", "Free RAM", sprintf("%dMB", free_mb), "→ Мало памяти!"); - let scale = 1.0; - let scale_path = "/etc/tachyon/mem_scale"; - let scale_data = fs.readfile(scale_path); - if (scale_data != null) { - let parsed_scale = double(trim(as_string(scale_data))); - if (parsed_scale > 0.1) scale = parsed_scale; - } - let new_scale = scale * 0.8; - if (new_scale < 0.2) new_scale = 0.2; if (!DOCTOR_REPAIR_MODE) { - doc_plan(sprintf("scale GOMEMLIMIT to %.2f + service restart", new_scale)); - doc_check("⚠️", "Free RAM", sprintf("%dMB", free_mb), sprintf("→ WILL FIX (doctor --fix): GOMEMLIMIT будет снижен до %.2f", new_scale)); + doc_plan("drop OS caches + sing-box restart"); + doc_check("⚠️", "Free RAM", sprintf("%dMB", free_mb), "→ WILL FIX (doctor --fix): сброс кэшей памяти и перезапуск sing-box"); } else { - fs.mkdir("/etc/tachyon"); - let scale_tmp = scale_path + ".tmp"; - if (fs.writefile(scale_tmp, sprintf("%.2f", new_scale)) != null) - fs.rename(scale_tmp, scale_path); - command_status("/usr/bin/tachyon restart >/dev/null 2>&1"); - doc_check("⚠️", "Free RAM", sprintf("%dMB", free_mb), sprintf("→ FIXED: GOMEMLIMIT снижен до %.2f, services перезапущены", new_scale)); + command_status("sync; echo 3 > /proc/sys/vm/drop_caches 2>/dev/null; /etc/init.d/sing-box restart >/dev/null 2>&1"); + doc_check("⚠️", "Free RAM", sprintf("%dMB", free_mb), "→ FIXED: кэши памяти сброшены, sing-box перезапущен"); fixed++; } } else { @@ -3013,30 +3000,16 @@ function run_doctor_checks_impl(repair) { issues++; let oom_victim_singbox = index(lc(logread_out), "killed process") >= 0 && match(lc(logread_out), /killed process[^\n]*sing-box/) != null; - let scale = 1.0; - let scale_path = "/etc/tachyon/mem_scale"; - let scale_data = fs.readfile(scale_path); - if (scale_data != null) { - let parsed_scale = double(trim(as_string(scale_data))); - if (parsed_scale > 0.1) { - scale = parsed_scale; - } - } - let new_scale = scale * 0.8; - if (new_scale < 0.2) new_scale = 0.2; if (!DOCTOR_REPAIR_MODE) { - doc_plan(sprintf("scale GOMEMLIMIT to %.2f", new_scale)); + doc_plan("clear system log + drop OS caches"); doc_check("❌", "System OOM checks", - oom_victim_singbox ? "OOM detected, sing-box was killed" : sprintf("OOM detected (current scale: %.2f)", scale), - sprintf("→ WILL FIX (doctor --fix): GOMEMLIMIT будет снижен до %.2f", new_scale)); + oom_victim_singbox ? "OOM detected, sing-box was killed" : "OOM detected in system logs", + "→ WILL FIX (doctor --fix): очистка логов и сброс кэшей памяти"); } else { - fs.mkdir("/etc/tachyon"); - let scale_tmp2 = scale_path + ".tmp"; - if (fs.writefile(scale_tmp2, sprintf("%.2f", new_scale)) != null) - fs.rename(scale_tmp2, scale_path); + command_status("sync; echo 3 > /proc/sys/vm/drop_caches 2>/dev/null; logread -c >/dev/null 2>&1; rm -f /etc/tachyon/mem_scale"); doc_check("❌", "System OOM checks", - oom_victim_singbox ? "OOM detected, sing-box was killed" : sprintf("OOM detected (current scale: %.2f)", scale), - sprintf("→ FIXED: Scaled GOMEMLIMIT to %.2f", new_scale)); + oom_victim_singbox ? "OOM detected, sing-box was killed" : "OOM detected in system logs", + "→ FIXED: журналы сброшены, кэши памяти освобождены"); fixed++; } } else { diff --git a/tachyon/files/usr/lib/service/ui.uc b/tachyon/files/usr/lib/service/ui.uc index b5e60ae7..e9c3dd11 100644 --- a/tachyon/files/usr/lib/service/ui.uc +++ b/tachyon/files/usr/lib/service/ui.uc @@ -1053,7 +1053,7 @@ function process_memory_rss_mb(process_name) { if (!pid || match(pid, /^[0-9]+$/) == null) continue; let cmd = fs.readfile("/proc/" + pid + "/cmdline"); - if (cmd && index(cmd, "check") >= 0) + if (cmd && (index(cmd, "check") >= 0 || (process_name == "sing-box" && index(cmd, "run") < 0))) continue; let status = fs.readfile("/proc/" + pid + "/status"); if (!status) diff --git a/tachyon/files/usr/lib/singbox/generator.uc b/tachyon/files/usr/lib/singbox/generator.uc index 4e3f89d9..7a060789 100644 --- a/tachyon/files/usr/lib/singbox/generator.uc +++ b/tachyon/files/usr/lib/singbox/generator.uc @@ -22,7 +22,6 @@ let fixture_uci_data = null; let runtime_settings_cache = null; let runtime_ruleset_folder = runtime_constants.TMP_RULESET_FOLDER; let runtime_supports_xhttp = true; -let HOSTS_CACHE_FILE = "/etc/tachyon/hosts-lists/combined.txt"; let as_string = common.as_string; let read_json_file = common.read_json_file; @@ -459,55 +458,6 @@ function base_config(settings, service_address, runtime_context) { } } - let hosts_cache_st = fs.stat(HOSTS_CACHE_FILE); - if (hosts_cache_st != null && int(hosts_cache_st.size) > 0) { - let fh = null; - try { - fh = fs.open(HOSTS_CACHE_FILE, "r"); - if (fh != null) { - let line; - while ((line = fh.read("line")) != null) { - line = trim(line); - if (line == "" || substr(line, 0, 1) == "#") - continue; - let parts = split(line, /[ \t]+/); - if (length(parts) >= 2) { - let p1 = parts[0]; - let p2 = parts[1]; - if (core_ip.valid_ip(p1)) { - let ip = p1; - let rr_type = index(ip, ":") != -1 ? "AAAA" : "A"; - for (let i = 1; i < length(parts); i++) { - let d = parts[i]; - if (d != "" && substr(d, 0, 1) != "#" && index(d, ":") == -1) { - push(dns_hosts_predefined, { - action: "predefined", - domain: [d], - answer: [d + ". 60 IN " + rr_type + " " + ip] - }); - } - } - } else if (core_ip.valid_ip(p2)) { - let domain = p1; - let ip = p2; - if (index(domain, ":") == -1) { - let rr_type = index(ip, ":") != -1 ? "AAAA" : "A"; - push(dns_hosts_predefined, { - action: "predefined", - domain: [domain], - answer: [domain + ". 60 IN " + rr_type + " " + ip] - }); - } - } - } - } - } - } catch(e) { - warn("Error reading hosts cache: ", as_string(e), "\n"); - } - if (fh) fh.close(); - } - for (let rule in dns_config.rules) push(dns_rules, rule); for (let rule in [ diff --git a/tachyon/files/usr/lib/singbox/runtime.uc b/tachyon/files/usr/lib/singbox/runtime.uc index 30f67aa4..400df534 100644 --- a/tachyon/files/usr/lib/singbox/runtime.uc +++ b/tachyon/files/usr/lib/singbox/runtime.uc @@ -369,7 +369,7 @@ function owner_pid() { function managed_service_installed() { let data = fs.readfile("/etc/init.d/sing-box"); - return data != null && index(as_string(data), SB_MANAGED_SERVICE_MARKER) >= 0 && index(as_string(data), "GOGC") >= 0; + return data != null && index(as_string(data), SB_MANAGED_SERVICE_MARKER) >= 0 && index(as_string(data), "GOGC=\"50\"") >= 0; } function managed_service_text() { @@ -381,7 +381,7 @@ function managed_service_text() { "start_service() {\n" + " config_load \"sing-box\"\n" + " local enabled config_file working_directory\n" + - " local log_stderr mem_total_kb mem_limit_mb gogc scale scale_pct\n\n" + + " local log_stderr\n\n" + " config_get_bool enabled \"main\" \"enabled\" \"0\"\n" + " [ \"$enabled\" -eq \"1\" ] || return 0\n\n" + " config_get config_file \"main\" \"conffile\" \"/etc/sing-box/config.json\"\n" + @@ -393,7 +393,7 @@ function managed_service_text() { " procd_set_param stderr \"$log_stderr\"\n" + " procd_set_param limits core=\"unlimited\"\n" + " procd_set_param limits nofile=\"1000000 1000000\"\n" + - " procd_set_param env GODEBUG=\"madvdontneed=1\"\n" + + " procd_set_param env GODEBUG=\"madvdontneed=1\" GOGC=\"50\"\n" + " procd_set_param term_timeout 15\n" + " procd_set_param respawn\n" + " procd_close_instance\n" +