From 54251fd2fc5f6a7e02a47595c7e088006a07cbeb Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Sat, 10 Oct 2026 17:23:18 -0700 Subject: [PATCH] docs: establish polling performance rules for coding agents (#8291) Signed-off-by: Thomas Vincent --- .github/copilot-instructions.md | 47 ++++++++++++++++++++++++ .github/instructions/php.instructions.md | 7 ++++ .gitignore | 1 - AGENTS.md | 22 ++++++++++- CLAUDE.md | 30 +++++++++++++++ 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 CLAUDE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 589dc2ef8..6df20a09f 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -98,6 +98,53 @@ - Do not commit Composer-installed package trees or hand-edit Composer-generated autoload metadata. Validate dependency changes with `composer validate` and a clean `composer install`. - If a third-party asset cannot be managed through Composer, stop and document the concrete packaging requirement before adding files. Do not silently create a vendored exception. +## Polling and script-server performance + +Treat polling performance as an architectural constraint when changing +`poller.php`, `cmd.php`, `script_server.php`, polling scripts, SNMP helpers, +subprocess wrappers, `lib/poller.php` or RRD update paths. Cacti installations +can have millions of data sources. Trace the actual call chain before adding +work: script-server launch, script include, function call, SNMP query, process +execution and individual SNMP requests. Preserve existing process reuse and +avoid introducing repeated includes, launches or network requests per sample. + +- Resolve shared metadata at template scope and cache it once per process or + explicitly defined polling cycle. Cache empty results with a separate loaded + flag or equivalent sentinel; an empty array must not cause another query on + every pass. Define invalidation for long-lived workers and configuration + changes so the cache does not serve stale metadata indefinitely. +- Do not query or scan individual data sources inside every loop to answer a + template-level question. Do not preload millions of source records as a + substitute. Source-specific state, ownership, graph bindings, orphan handling + and permissions still require correct source-specific checks; sharing a + template does not make those values interchangeable. Batch necessary reads + and keep cache cardinality and memory bounded. +- Do not add fixed sleeps to each subprocess or SNMP call. Prefer readiness + waiting and monotonic deadlines where supported, while preserving active + output handling, silent-child timeouts, exit status and resource cleanup. + Measure overhead relative to direct execution. An extra 50 ms across 20,000 + serialized calls adds approximately 1,000 seconds before useful work. +- Confirm the implementation on the target branch. `cacti_exec()` and transport + implementations differ across release branches; a fix or test for one branch + must not be assumed applicable to another. +- Treat credential caching as a separate optimization. Measure hit rates, + avoided lookups, time and memory before claiming a benefit. Preserve device, + poller and credential identity, invalidation and secret-handling boundaries; + never log secrets as performance evidence. Credential caching does not fix + repeated template queries or per-call process delays. +- For changes to these paths, run applicable polling performance regressions. + Instrument query and call counts over repeated passes, including empty-cache + results. Compare subprocess wrapper overhead with direct execution and cover + streaming output, silent-child timeouts and exit codes. Exercise representative + synthetic scales, including 150k, 1M and 2.5M sources where the branch's harness + supports them, and record runtime, elapsed time and peak memory. Keep timings + from hosted runners diagnostic; use reproducible count-based regressions and + tests that detect reintroduced repeated queries or fixed delays. +- Label synthetic PHP processing results as synthetic. They do not establish + real RTM throughput, database query plans, SNMP/Spine performance, RRD I/O, + remote replication or full Boost behavior. Production-scale claims require a + representative end-to-end benchmark, including those costs. + ## Database Optimization (DBA Mode) - **Context**: The full schema (DDL/DML) is in `cacti.sql`. Check it for table structures and indexes. - **Optimize**: Proactively look for slow query patterns (e.g., missing indexes, non-sargable `WHERE` clauses). diff --git a/.github/instructions/php.instructions.md b/.github/instructions/php.instructions.md index 67e0d918b..c57c6df3a 100644 --- a/.github/instructions/php.instructions.md +++ b/.github/instructions/php.instructions.md @@ -55,6 +55,13 @@ Use these instructions for PHP changes in Cacti organization repositories. Repos - Avoid `SELECT *` in production queries. Select the required columns and check the schema and indexes before changing a performance-sensitive query. - Make schema installation and upgrades idempotent and safe for existing installations. Preserve data unless a clearly named, authorized migration intentionally changes it. +## Polling performance + +- For polling, script-server, SNMP, subprocess and RRD update changes, follow the detailed polling performance rules in the repository's `.github/copilot-instructions.md` and `AGENTS.md`. Inspect the actual branch's call chain before adding work to a loop. +- Cache shared template metadata once per process or explicit cycle, including empty results, with appropriate invalidation. Avoid repeated per-source metadata reads and caches that grow to millions of entries for a template-level lookup. Preserve source-specific correctness. +- Avoid fixed per-call sleeps and repeated launches, includes or SNMP requests introduced by wrappers. Measure wrapper overhead against direct execution and preserve streaming output, timeouts, exit status and cleanup. +- Verify repeated query/call counts and memory at representative scales. Measure credential-cache benefits separately. Label synthetic results accurately; production throughput claims require representative end-to-end evidence. + ## Files, commands, logging, and secrets - Treat file paths and archive contents as untrusted. Constrain them to the intended base directory and reject traversal or unexpected file types. diff --git a/.gitignore b/.gitignore index bf80554e2..b38193599 100644 --- a/.gitignore +++ b/.gitignore @@ -122,7 +122,6 @@ docker-compose.override.yml .claude/** # Security research artifacts (never commit) -CLAUDE.md reproduce_ghsa_*.php verify_task*.php .gemini_security/ diff --git a/AGENTS.md b/AGENTS.md index 73322e175..a67882bdf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,8 +5,8 @@ Applies to Claude, Codex, and any other agent working in this repository. directly. Read that first and follow it. This file covers the points that are easiest to get wrong, and does not repeat the rest. -`CLAUDE.md` is gitignored on purpose (it holds local security-research notes), -so shared agent guidance belongs here. +`CLAUDE.md` contains shared repository guidance. Keep private security-research +notes outside tracked instruction files and follow `SECURITY.md` for reporting. ## Where tests go @@ -71,6 +71,24 @@ composer test -- --testsuite=Unit Match the PHP version declared by `composer.json` and the CI matrix rather than whatever is on `PATH`. Report which version produced a result. +## Polling performance is an architectural constraint + +Read the polling performance section in +[.github/copilot-instructions.md](.github/copilot-instructions.md) before changing +poller, script-server, SNMP, subprocess or RRD update paths. These paths can serve +millions of data sources; repeated work inside their loops must be justified. + +Cache shared template metadata once per process or explicit polling cycle, +including empty results. Do not replace that cache with per-data-source lookups +or load millions of source records to answer a template-level question. Preserve +source-specific correctness and bounded memory. Avoid fixed per-call sleeps and +repeated process launches, includes or SNMP requests introduced by wrappers. + +Verify query/call counts, subprocess overhead and cache lifecycle using the +target branch's actual code. Synthetic scale tests are regression evidence, +not proof of production RTM throughput. Credential-cache benefits require +measurement; they do not excuse repeated metadata work or process delays. + ## Never vendor dependencies Do not add, copy, or update third-party package source under `include/vendor/` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..4b12ad77b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,30 @@ + + +# Cacti coding guide + +Read [AGENTS.md](AGENTS.md) and [.github/copilot-instructions.md](.github/copilot-instructions.md). +The Copilot document contains the established application conventions; AGENTS +adds test organization, path-depth and dependency rules. Keep shared guidance +free of private security-research notes. + +Use `mise` for the PHP/Node versions declared by Composer, `.nvmrc` and CI. +Use `composer check` for the canonical checks and +`composer test -- --testsuite=Unit` for focused PHP tests after dependency setup. +Run `npm ci` and `npm test` for frontend changes; the install rebuilds managed +assets, so review generated diffs and preserve `build/` and `patches/` inputs. + +Preserve prepared DB helpers, validated request wrappers, auth/CSRF boundaries, +context-specific output escaping and remote-poller behavior. Place Pest tests in +category subfolders; never shadow production functions or hand-edit autoloaders. +Do not refresh vendored packages by copying source. Preserve runtime directory +security guards, GPL notices and the exact branch's compatibility contracts. +No live database migration or polling is part of ordinary offline verification. + +For poller, script-server, SNMP, subprocess and RRD update work, follow the +polling performance sections in AGENTS and the Copilot instructions. Cache +template metadata once per process or defined cycle, including empty results; +avoid repeated source lookups, launches and fixed per-call sleeps. Preserve +source-specific correctness, cache invalidation and bounded memory. Verify +query/call counts and subprocess overhead on the actual target branch. Measure +credential-cache benefits separately, and never present synthetic scale tests +as proof of production RTM throughput.