
TickBudget
Tick budget runner, adaptive fair-share time pool, and thread diagnostics for Paper and Folia.
TickBudget
A shared tick-time budget for Paper and Folia plugins. Plugins run long jobs in small slices, and TickBudget divides the available milliseconds between them.
TickBudget is a library plugin. It does nothing on its own until another plugin uses it, but it gives admins a command that shows which plugin spends how much tick time.
For server owners
If a plugin you run lists TickBudget as a dependency, drop the jar into plugins/ and restart. There is nothing to set up. The defaults work for most servers.
- Per-plugin tick usage -
/tickbudget statusshows each plugin's CPU time over the last 60 seconds, plus completed steps, deferred ticks and thread violations since startup. - Top tasks -
/tickbudget toplists running tasks by total CPU time. - Fair sharing - each plugin gets a guaranteed minimum per tick. The rest of the free time is split by task priority, so one plugin cannot use up the whole tick.
- Paper and Folia - the plugin detects the platform at startup and uses the matching scheduler.
Requires Java 21. Tested on Paper 1.21 to 26.3 and on every Folia build from 1.21.4 to 26.2.
Commands
Everything uses the permission tickbudget.admin, which operators have by default.
/tickbudget status Platform, active task count and per-plugin usage
/tickbudget top Running tasks sorted by CPU time
/tickbudget debug <on|off> Log details when a task touches the wrong thread
/tickbudget reload Reload config.yml
Configuration
# Time left unused in each tick for the server itself (ms)
safety-margin-ms: 5.0
# Minimum time each active plugin gets per tick (ms)
floor-budget-ms: 0.5
# Budget for tasks that do not set their own (ms)
default-task-budget-ms: 1.0
# Largest budget any task may use per tick, CRITICAL included (ms)
max-task-budget-ms: 20.0
Share of the free time by task priority
priority-weights: low: 1 normal: 2 high: 4 critical: 8
debug: false
Anonymous usage statistics through bStats
metrics: true
### For plugin developers
A task is split into steps. TickBudget runs as many steps as fit into the budget each tick and continues on the next tick.
```java
TickBudget tb = TickBudget.of(plugin);
tb.run(Target.region(location), BudgetedTask.iterate(blocks, block -> block.setType(Material.AIR)))
.name("clear-ruins")
.budget(Budget.millisPerTick(1.5))
.priority(Priority.NORMAL)
.onComplete(() -> plugin.getLogger().info("Done"))
.onError(error -> plugin.getLogger().severe(error.getMessage()))
.start();
A step returns MORE (keep going if the budget allows), YIELD (nothing more this tick, continue later) or DONE. Long-lived workers that drain a sometimes-empty queue should return YIELD when idle, so they cost one cheap step per tick instead of their whole budget.
- Targets -
Target.global(),Target.region(location),Target.entity(entity)andTarget.async(). On Folia each one maps to the matching scheduler. On Paper, global, region and entity run on the main thread and async runs off it. - Thread checks -
tb.assertOn(target)throws if the current thread does not own the target. - Async chunks -
tb.chunks().loadAsync(world, x, z)loads a chunk without blocking.
Add the API through JitPack and do not shade it:
repositories { maven("https://jitpack.io") }
dependencies { compileOnly("com.github.denfry:tickbudget:v0.3.0") }
Then add depend: [TickBudget] to your plugin.yml, or softdepend: [TickBudget] with a fallback timer if your plugin should also run without it. The README has a ready-made fallback class. The API jar is also attached to every GitHub release.
Metrics
TickBudget reports anonymous statistics (server platform, number of plugins using it, number of active tasks) to bStats. Set metrics: false in config.yml to turn it off.
Links
- Source code
- Report a bug
- bStats
Released under the MIT License.
Сервер для плагина TickBudget - как у профи
Плагин TickBudget создан для серверов: на своём сервере вы настраиваете его под себя и решаете, кому играть. Создать сервер с плагином TickBudget для друзей можно за пару минут - BungeeHost всё уже подготовил.
