Repository navigation
Expand file tree
/
Copy pathtaskguard.example.toml
More file actions
176 lines (163 loc) · 8.82 KB
/
Copy pathtaskguard.example.toml
File metadata and controls
176 lines (163 loc) · 8.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# taskguard settings.
#
# Copy this to ~/.config/taskguard/config.toml, or put the parts that belong to
# one repository in a .taskguard.toml at the root of that repository.
#
# Later layers win:
# 1. built-in defaults
# 2. ~/.config/taskguard/config.toml (this file)
# 3. [dir."<path>"] sections in this file (the longest matching path wins)
# 4. .taskguard.toml in the repository (walked up from the job's cwd)
# 5. command-line flags
#
# Settings live in files, not in environment variables: turbo's default strict
# env mode drops variables it does not know, so an exported variable looks
# like it works and silently does nothing.
#
# Check what applies where you are: taskguard doctor
# Check how one command is treated: taskguard doctor --explain "bunx vitest run"
# enabled = false # every command runs straight through, unqueued and unmeasured
# --------------------------------------------------------------- limits ----
# A job starts only when
# CPU busy + CPU still promised to running jobs + its CPU need fits under cpu_max
# memory held + memory still promised to running jobs + its memory need fits under mem_max
# Needs are learned per command: memory is the highest peak of the last
# hist_keep runs (outliers held back, see learning), CPU the cores it used
# (not the time it waited for a core), the newest runs counting most and
# outliers held back the same way. A memory need is capped at mem_max.
cpu_max = 100 # percent of all cores
mem_max = 85 # percent of RAM
pressure_max = 20 # nothing new starts at this memory pressure (macOS: 50 warning, 100 critical)
warn_admit = true # macOS warning: jobs still start while memory fits and no first run grows; false = warning stops all
# ------------------------------------------------------------ auto pause ----
# Off by default. When memory in use reaches pause_at, taskguard pauses a
# running job (SIGSTOP on the command and every process below it): the one
# with the lowest priority, newest first. One job always keeps running, and
# --now jobs are never paused. A paused job keeps its memory, but it stops
# growing, and macOS or Linux can compress it or move it to swap. Nothing new
# starts while a job is paused. It resumes (SIGCONT) when memory is under
# resume_at, or when no other job runs. Its paused time is not counted as run
# time. Change it with ←/→ in taskguard top, view 8.
auto_pause = false
pause_at = 92 # percent of RAM in use; the kernel's critical pressure also counts
resume_at = 80 # percent of RAM in use; kept at least 2 under pause_at
# -------------------------------------------------------------- priority ----
# A waiting job with a higher priority starts before jobs with a lower one:
# they wait while it waits, unless its own pool is full. With backfill
# (max_backfill), jobs that fit start while it cannot, as for a reserved job. Jobs with the same
# priority keep the order they came in. Set it per directory, per repository,
# per command ([[job]] below), or for one call with --priority N.
priority = 0
# ---------------------------------------------------------------- hints ----
# Extra words for LLM agents on every status line ("this is not a hang",
# "starts when X finishes"), and advice after a starved run. On by default.
# Switch off per repository or directory, not per command. --hints and
# --no-hints override it for one call.
hints = true
# ------------------------------------------------------------- learning ----
hist_keep = 10 # how many past runs feed the learned needs
learn_stagger = 5 # a batch of jobs with no history starts after the last one ran this long
new_job_mem = "1.5G" # memory a job with no history reserves when no similar job is known
cpu_min_duration = 5 # jobs that usually end sooner than this skip the CPU check
max_bypass = 120 # seconds a job may be passed by newer ones before it is reserved
max_backfill = 600 # until a reserved job has waited this many seconds, newer jobs that fit
# may start while it cannot; after that, only those that should end
# before it could start anyway, so the machine drains for it.
# 0 (or anything up to max_bypass) = never.
# taskguard 0.1.6 and older reject a file that sets it.
boost_runs = 5 # runs that get +25% memory after a memory-starved run
# A peak more than outlier_ratio times the next peak below it, and outlier_min
# above it, is an outlier. Outliers count by outlier_weights: the first entry
# when there is one, the second when there are two, in full past the list. A
# run that failed never counts above the runs that passed. Jobs that usually
# take under outlier_min have no outliers. See them with taskguard outliers.
# 0 turns it off.
outlier_ratio = 1.5
outlier_min = "1G"
outlier_weights = [0, 0.5]
# A job that falls short by this little starts anyway, with a warning.
noise_mem = 2 # percent of RAM
noise_cpu = 0.5 # cores
# A job that only programs outside taskguard keep out starts anyway, with a
# warning, while memory stays under pause_at.
outside_admit = true
# A job that cannot fit now (its CPU need is above the whole limit, or it has
# waited past max_bypass) starts on this share of its CPU need, once the
# machine is near its lowest CPU use of the last two minutes. It books the
# cores it got. Memory is still checked. 0 turns it off. Set it per machine.
partial_fit = 0.5
# ---------------------------------------------------------------- timing ----
sample_every = 2 # seconds between measurements of a running job
status_every = 120 # seconds between "still waiting" lines
wait_check_every = 0.1 # seconds between a waiting job's cheap look: did a job join or leave?
wait_decide_every = 1 # a waiting job decides again at least this often; raise both to
# spend less CPU on long queues, lower them to start jobs sooner.
# taskguard 0.5.0 and older reject a file that sets them.
# ------------------------------------------------------------- recorder ----
recorder_idle_exit = 1800 # the recorder exits after this many idle seconds
retention_raw_hours = 48 # keep 2-second samples this long
retention_rollup_days = 90 # keep one-minute averages this long
# ----------------------------------------------------------- passthrough ----
# Commands that run straight through, unqueued and unmeasured, on top of the
# built-in list (watch modes, dev servers, --version, --help).
# passthrough = ["storybook", "my-dev-server"]
# Top-level settings end here: in TOML, a key written after a [table] line
# belongs to that table.
# ---------------------------------------------------------------- pools ----
# A pool only adds a slot ceiling: jobs that share one database, set of
# services or files run one (or max_slots) at a time, so they cannot break each
# other. CPU and memory are always shared by the whole machine. Built-in
# single-slot pools: db, e2e, integration. Change them here or in
# the Config view of taskguard top. A pool counts per worktree; set
# per_checkout to false for one pool for the whole machine.
#
# [pool.e2e]
# max_slots = 2
#
# [pool.docker]
# max_slots = 1
# per_checkout = false
# match = ["docker compose up", "docker build"]
#
# Take away a built-in pool's ceiling, so only CPU and memory decide:
# [pool.db]
# unlimited = true
#
# Jobs that run until someone stops them, such as dev stacks: each starts when
# there is room for its start-up peak and holds that peak for `startup`
# seconds (300 by default). After that its needs follow what it uses, so an
# idle stack does not keep the cores it took while it started. A [[job]] rule
# can set both too; its long_lived wins over its pool's.
# [pool.stack]
# max_slots = 4
# long_lived = true
# startup = 600
# ---------------------------------------------------------- job rules ----
# Per-command settings. `match` is a pattern: the command word, then words that
# must appear among its arguments, in order. Launchers such as bun, bunx, npx,
# pnpm exec and node are stripped first. `key` matches the history key instead
# (see taskguard history), with * and ** globs.
#
# [[job]]
# match = "vitest run --project integration"
# min_cpu = 4 # never start with fewer than 4 free cores
# min_mem = "6G" # never start with less than 6 GB free
#
# [[job]]
# key = "packages/api:*"
# pool = "e2e"
# priority = 1 # starts before jobs with priority 0
#
# [[job]]
# match = "tsc -p tsconfig.quick.json"
# now = true # always skip the queue, but still measure it
# ---------------------------------------------------- per-directory settings ----
# Settings for jobs whose cwd is inside a path, without touching the repository.
#
# [dir."/Users/me/code/dalp"]
# hints = false
# mem_max = 80
#
# [[dir."/Users/me/code/dalp".job]]
# match = "hardhat test"
# min_mem = "12G"