{"id":31074146,"url":"https://github.com/criccomini/memmark","last_synced_at":"2026-05-18T09:07:40.710Z","repository":{"id":311817381,"uuid":"1045181822","full_name":"criccomini/memmark","owner":"criccomini","description":"A simple, portable benchmarker for process memory usage","archived":false,"fork":false,"pushed_at":"2025-08-26T23:15:59.000Z","size":26,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-16T02:22:20.771Z","etag":null,"topics":["bash","performance","performance-testing","scripts"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/criccomini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-26T19:18:16.000Z","updated_at":"2025-08-30T07:15:50.000Z","dependencies_parsed_at":"2025-08-27T03:33:24.780Z","dependency_job_id":"4fa2d77d-dcb2-4771-989a-416e5055865b","html_url":"https://github.com/criccomini/memmark","commit_stats":null,"previous_names":["criccomini/memmark"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/criccomini/memmark","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/criccomini%2Fmemmark","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/criccomini%2Fmemmark/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/criccomini%2Fmemmark/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/criccomini%2Fmemmark/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/criccomini","download_url":"https://codeload.github.com/criccomini/memmark/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/criccomini%2Fmemmark/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33172173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T05:43:36.989Z","status":"ssl_error","status_checked_at":"2026-05-18T05:43:19.133Z","response_time":71,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","performance","performance-testing","scripts"],"created_at":"2025-09-16T02:03:48.589Z","updated_at":"2026-05-18T09:07:40.680Z","avatar_url":"https://github.com/criccomini.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# memmark\n\nSingle-file Bash tool to sample memory usage of a target process and its entire descendant tree over time. It writes a CSV file and can optionally render charts if gnuplot is installed.\n\n## Features\n\n- CSV output of memory usage over time\n- Accepts a PID to attach to, or a command to launch and track\n- Aggregates memory across all child processes (recursively)\n- Portable: macOS and Linux (graceful fallbacks per-OS)\n- Optional charts via gnuplot (if installed)\n\n## Installation\n\n- Install using the provided `install.sh` script:\n    ```sh\n    curl -sL https://github.com/criccomini/memmark/raw/main/install.sh | bash\n    ```\n- Requirements:\n  - bash ≥ 3.2 (works with the default macOS bash)\n  - Standard UNIX tools: `ps`, `awk`, `grep`, `sed`, `date`\n  - Linux: `/proc` available for detailed metrics\n  - macOS optional: `vmmap` (ships with Xcode tools) for physical footprint and region counts\n  - Optional: `gnuplot` for chart generation\n\n## Usage\n\nTrack an existing PID:\n```sh\nmemmark --pid 12345 --interval 1s --out run.csv --chart run.png\n```\n\nRun and track a command until it exits:\n```sh\nmemmark --interval 500ms --out train.csv -- python train.py --epochs 3\n```\nOn Linux, add `--smaps` to collect PSS/swap via smaps.\nStop conditions:\n- If tracking a command, memmark exits when the command exits (and returns the command's exit code).\n- If attaching to a PID, memmark exits when the root PID exits or when `--duration` is reached, whichever comes first.\n\n## What memmark measures\n\nMemmark samples once per interval and sums metrics across the tracked process and all of its descendants:\n\n- rss_kib: Resident Set Size sum in KiB (macOS+Linux via `ps`)\n- vsz_kib: Virtual memory size sum in KiB (macOS+Linux via `ps`)\n- swap_kib: Swap in KiB (Linux via `/proc/*/smaps` when `--smaps` is enabled; blank on macOS)\n- pss_kib: Proportional Set Size in KiB (Linux via `/proc/*/smaps` when `--smaps` is enabled)\n- phys_footprint_kib: macOS Physical Footprint (via `vmmap -summary`, optional)\n- mapped_regions: Count of mapped regions (Linux via `/proc/*/maps` line count; macOS via `vmmap` region count, optional)\n- pid_count: Number of processes included in the sample\n\nNotes:\n- Some metrics are best-effort and platform-dependent. If a metric is unavailable, the CSV column remains empty for that sample.\n- Reading `/proc/*/smaps` can be slower; memmark defaults to fast mode. Use `--smaps` to enable PSS/swap collection.\n\n### CLI\n\n- `--pid \u003cPID\u003e`: Track an existing process. Mutually exclusive with running a command.\n- `-- \u003cCOMMAND ...\u003e`: Everything after `--` is executed and tracked as the root process.\n- `--interval \u003cDURATION\u003e`: Sampling interval (e.g., `200ms`, `1s`, `2m`). Default: `1s`.\n- `--duration \u003cDURATION\u003e`: Maximum duration to run. Default: run until target exits.\n- `--out \u003cPATH\u003e`: CSV output path. Use `-` for stdout. Default: `memmark.csv` in CWD.\n- `--smaps`: On Linux, parse `/proc/\u003cpid\u003e/smaps` to collect PSS and swap (higher overhead; disabled by default).\n- `--chart \u003cPATH\u003e`: If set and gnuplot is available, render a PNG chart to this path.\n\n### CSV schema\n\nColumns (superset; some may be empty depending on OS and flags):\n- `timestamp`: ISO-8601 wall time of the sample\n- `unix_ms`: Unix epoch in milliseconds\n- `root_pid`: The original root PID (command or attached PID)\n- `pid_count`: Number of processes included in the sample\n- `rss_kib`: Sum of RSS across the tree (KiB)\n- `vsz_kib`: Sum of VSZ/VSIZE across the tree (KiB)\n- `swap_kib`: Sum of swap usage across the tree (KiB; Linux, optional)\n- `pss_kib`: Sum of PSS across the tree (KiB; Linux, optional)\n- `phys_footprint_kib`: Physical footprint (macOS, optional)\n- `mapped_regions`: Total mapped regions (best-effort)\n\nExample snippet:\n```csv\ntimestamp,unix_ms,root_pid,pid_count,rss_kib,vsz_kib,swap_kib,pss_kib,phys_footprint_kib,mapped_regions\n2025-08-26T18:10:00Z,1756231800000,12345,3,81234,540000,1200,76000,,420\n2025-08-26T18:10:01Z,1756231801000,12345,4,84567,541200,1300,77000,,431\n```\n\n## Charts (optional)\n\nIf `gnuplot` is installed and `--chart \u003cpng\u003e` is provided, memmark will generate a time series chart using the CSV it produced.\n- By default, it renders RSS, VSZ, and (if present) SWAP as lines.\n\nThe script embeds a minimal gnuplot program, so no extra files are required.\n\n## How it works (high level)\n\n- Every interval, build the descendant process set starting from the root PID.\n  - Linux: `ps -e -o pid=,ppid=` and `/proc` for details\n  - macOS: `ps -eo pid=,ppid=` and `ps -o` for metrics; `vmmap` optionally\n- Query per-process metrics and sum across the set.\n- Write one CSV row per sample.\n- Optionally invoke gnuplot to render a PNG.\n\n## Platform notes\n\n- macOS:\n  - `rss_kib` and `vsz_kib` from `ps` (KiB). `swap_kib` is typically unavailable; `vmmap -summary \u003cpid\u003e` may provide a physical footprint estimate (`phys_footprint_kib`).\n  - Access to `vmmap` output may require proper permissions; if unavailable, memmark will omit those columns.\n- Linux:\n  - `rss_kib` and `vsz_kib` from `ps`. `swap_kib` and `pss_kib` parsed from `/proc/\u003cpid\u003e/smaps` when `--smaps` is enabled.\n  - Reading `smaps` for many processes can add overhead; it is disabled by default. Use `--smaps` to enable.\n\n## Performance \u0026 overhead\n\n- Default interval is 1s; reduce (e.g., 200ms) for finer granularity but expect higher overhead.\n- By default memmark avoids expensive smaps reads; enable `--smaps` to collect PSS/swap (higher overhead).\n\n## Exit codes\n\n- When running a command: memmark returns the command's exit code.\n- When attaching to a PID: returns 0 on normal completion.\n\n## Troubleshooting\n\n- Empty `swap_kib` on macOS: expected; per-process swap is not generally available.\n- Permission denied on `/proc/\u003cpid\u003e/smaps`: you may not have rights to inspect processes owned by other users.\n- No charts produced: ensure `gnuplot` is installed and that `--chart` was provided.\n\n## Roadmap\n\n- Per-process breakdown mode (`--per-process` extra CSV)\n- CGroup/container memory awareness (Docker, Kubernetes)\n- Additional charts (stacked area for RSS/Swap)\n- Homebrew formula and release tarballs\n\n## License\n\nMIT License.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcriccomini%2Fmemmark","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcriccomini%2Fmemmark","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcriccomini%2Fmemmark/lists"}