Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

G1 Tuning For Slo

ASecurity

Deriving G1 flag values from a latency SLO and proving they helped: what `MaxGCPauseMillis` actually controls, the young size bounds, IHOP and adaptive IHOP with an explicit safety margin, region size as the basis of every region-denominated calculation, `G1OldCSetRegionThresholdPercent` and `G1MixedGCCountTarget`, and the measure-derive-predict-validate loop. Use when GC flags were copied from another service, when `-Xms` differs from `-Xmx` in production, when mixed GC violates the SLO whil...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentgojavagcpgit

Works with

cli

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add robsonkades/agent-skills --skill g1-tuning-for-slo --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of G1 Tuning For Slo?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for G1 Tuning For Slo
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/robsonkades-g1-tuning-for-slo/badge)](https://www.skillsdirectory.com/skills/robsonkades-g1-tuning-for-slo)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: g1-tuning-for-slo
description: >
  Deriving G1 flag values from a latency SLO and proving they helped: what
  `MaxGCPauseMillis` actually controls, the young size bounds, IHOP and adaptive IHOP with
  an explicit safety margin, region size as the basis of every region-denominated
  calculation, `G1OldCSetRegionThresholdPercent` and `G1MixedGCCountTarget`, and the
  measure-derive-predict-validate loop. Use when GC flags were copied from another service,
  when `-Xms` differs from `-Xmx` in production, when mixed GC violates the SLO while young
  GC is healthy, when GC overhead exceeds its explicit service budget, when a full GC follows a marking
  cycle that finished too late, when an IHOP was set to the theoretical ceiling, when a G1
  flag makes the JVM refuse to start, or when a parser reports a promotion rate of zero.
  Does not cover deciding whether GC is the bottleneck at all or which collector to use
  (jvm-gc-tuning), why the mechanism responds the way it does (g1-internals), or
  configuring and parsing the GC log itself (gc-log-analysis).
---

# G1 Tuning For SLO

## Purpose

Derive candidate G1 flag values from a stated latency SLO, with a traceable measurement
behind each one, and test whether the change helped. Every flag in this space moves the
system inside a fixed triangle of pause, throughput and footprint — none of them removes
the trade-off, so a change without a recorded trade-off is a change nobody can defend.

The failure this prevents is tuning by transplant. Two services with the same SLO need
different G1 configurations when their allocation rate, promotion rate or average object
size differ. A configuration that "worked" elsewhere is at best a starting point for
measurement, and at worst hides the actual cause behind a symptom that moved.

## Workflow

1. **Reuse the stated SLO, workload and deployment context.** Confirm the request population,
   clock, success/error treatment, threshold and window, plus CPU/memory budgets and the actual
   JDK vendor/update, collector and flags. Preserve the project's target; the implementation
   examples here use HotSpot JDK 25. Retain an adequate configuration; a flag change is not
   required. If GC attribution is missing, carry existing evidence to `jvm-gc-tuning` or
   `pause-attribution` before deriving values.
2. **Use enough complete cycles across representative regimes.** Reuse adequate captures;
   `-Xlog:gc*` supplies broad info-level coverage, while explicit tag selections can supply
   the same required evidence. Add the policy tags in
   [the policy log](references/policy-log-and-troubleshooting.md) if the question is
   _why_ G1 chose a size. Confirm current defaults and the effective region size with
   `-XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version` with the target flags
   on the target runtime. Bound any missing capture by existing authorization, known process
   identity, overhead and storage constraints. Thirty minutes may be adequate for a
   steady high-rate service and useless for a diurnal/bursty one; justify sample/cycle count and
   include startup, peak, recovery or soak windows relevant to the SLO.
3. **Measure the inputs**: allocation rate, old-generation allocation/promotion pressure,
   object survival and live-set behavior across the load regimes that matter. Region-count
   deltas are estimates, not exact byte ledgers; validate them against policy logs or JFR.
4. **Name the failing event before choosing a lever.** Young pauses over budget, mixed
   pauses over budget, a full GC after marking, an evacuation failure and a GC-overhead
   problem need different evidence and candidate controls; the
   [symptom table](references/policy-log-and-troubleshooting.md) maps them.
5. **Derive only the implicated controls, showing the arithmetic**: young bounds from the
   young SLO; `G1OldCSetRegionThresholdPercent` and `G1MixedGCCountTarget` together from
   the mixed SLO; IHOP from old-generation allocation rate and observed marking time, with an explicit
   safety margin below the theoretical ceiling.
6. **Write the prediction down before running the validation.** A prediction recorded
   afterwards cannot be wrong, which makes the validation worthless.
7. **Validate under load equivalent to the baseline**, evaluating young and mixed
   collections separately, and recompute GC overhead from the new data rather than
   assuming it moved.
8. **Check for a regression elsewhere** — heap footprint, total CPU, latency on another
   route — before declaring the change good.

Return the supported decision (retain, canary, revert or collect missing evidence), the
candidate's measurement and prediction, actual validation scope/results and rollback conditions.

## Rules

- `MaxGCPauseMillis` (default 200) is a goal, not a guarantee. It sizes the young
  generation through the G1 policy; it does not bound a mixed collection under pressure,
  and minimum old-region work can exceed its predicted budget (below). Actual pause and
  request-SLO outcomes require elapsed-time evidence.
- `G1NewSizePercent`, `G1MaxNewSizePercent`, `G1OldCSetRegionThresholdPercent` and
  `G1MixedGCLiveThresholdPercent` are **experimental** on JDK 25. Without
  `-XX:+UnlockExperimentalVMOptions` placed _before_ them the JVM refuses to start
  (`VM option 'G1NewSizePercent' is experimental and must be enabled via ...`, executed
  on 25.0.3). A command line copied from a document that omits the unlock is not a
  configuration; it is an outage at the next restart.
- Every calculation denominated in "regions" requires the effective region size first. The
  ergonomic default, absent an explicit region-size request, is
  `-Xmx / 2048`, clamped to [1 MB, 32 MB], then rounded **up** to a power of two —
  `-Xmx5g` gives 4 MB, not 2 MB, and `-Xmx12g` gives 8 MB (executed on 25.0.3). `-Xms`
  plays no part. Confirm it with
  `java -Xmx<size> -XX:+PrintFlagsFinal -version | grep G1HeapRegionSize`.
- Use **binary** GB throughout a derivation. `-Xmx8g` is 8192 MiB, not 8000 MB. Mixing
  the conventions inside one derivation produces numbers that do not reconcile.
- Prefer `-Xms = -Xmx` when predictable heap ergonomics and pause-free expansion are worth a
  stable memory commitment. G1 sizes the young generation against currently available/committed
  capacity, so a very small `-Xms` can start with a
  tiny young generation and a GC storm (`-Xms64m -Xmx2g`: 23 Eden regions and 508 young
  GCs in 8 s against 481 regions and 154 GCs with `-Xms2g`, executed on 25.0.3), and
  expansion policy runs around GC pauses. Keep a smaller `-Xms` when elastic footprint/startup
  density is more valuable and measured warm-up/expansion meets the SLO. `-Xms` commits heap
  logically; physical residency depends on page touching—`AlwaysPreTouch` deliberately changes
  that cost. Container budgeting is `jvm-gc-tuning`.
- Size the young generation from the allocation rate — `young ≥ alloc_rate × target
interval` — and the heap from the live set plus that young generation plus
  `G1ReservePercent` (default 10) plus the old growth that accrues during marking. The
  live-set measurement itself is `jvm-gc-tuning`.
- Set an explicit GC CPU/pause-overhead budget from service capacity and SLO rather than a
  universal 5%. Compute STW overhead as `pause / wall interval` (or equivalently for one
  pause-cycle, `pause / (mutator interval + pause)`) and separately account concurrent GC CPU.
  High overhead can form a feedback loop through CPU starvation, queues and live objects, but
  the threshold is workload/headroom dependent. If tuning cannot meet the declared budget,
  reduce allocation/live set, add capacity or reconsider the collector.
- IHOP compares old-generation occupancy (including humongous occupancy) with an effective
  old/heap-capacity-derived threshold. A post-reclamation old live set near/above it can cause
  back-to-back cycles and little useful mixed reclaim, but does not logically prevent a mixed
  phase. Distinguish live-set pressure, old allocation during marking, humongous triggers and
  candidate efficiency; an IHOP adjustment cannot create reclaimable garbage.
- Do not set a static IHOP at a theoretical capacity ceiling. The ceiling assumes observed old-
  allocation rate and marking time repeat exactly. Adaptive IHOP incorporates predicted marking
  duration/allocation and reserve/waste/young constraints whose exact formula and flag names
  evolve. Read predictor state/target occupancy from `gc+ihop` and qualifying initiation
  checks from `gc+ergo+ihop`; missing initiation lines do not prove no marking need. Do not claim a
  hand-calculated constant is a bound the JVM will “never” cross.
- `G1UseAdaptiveIHOP` is `true` by default. The initial threshold applies until both
  marking-time and allocation-rate histories have `G1AdaptiveIHOPNumInitialSamples`
  (default 3) eligible samples. Completed cycles alone do not establish that state; check
  `prediction active`. The static value still matters at startup and after restart.
- `G1OldCSetRegionThresholdPercent` (default 10) sets a marking-candidate selection limit —
  `ceil(percent × committed regions)` — not a pause bound. The count-target minimum and
  indivisible groups can exceed that numeric limit; retained candidates have separate selection.
  G1 orders candidates by efficiency, but a uniform-cost estimate can be optimistic or pessimistic.
- `G1MixedGCCountTarget` (default 8) is a target for spreading candidate reclamation across
  mixed collections, not a guaranteed count. In the JDK 25 implementation it contributes
  a minimum of `ceil(initial marking candidates / target)` old regions, not recalculated from
  the shrinking remainder; that minimum can override the
  percent cap when the two disagree
  (`G1MixedGCCountTarget=1` with a 1 percent cap of 11 regions logged
  `Min 18 regions, max 18 regions` and a predicted 8.59 ms against a 5 ms target,
  executed on 25.0.3). Lowering it tends to concentrate old-region work; raising it tends
  to spread work and is a candidate for mixed-pause overshoot. Policy prediction,
  candidate groups and `G1HeapWastePercent` can still produce fewer/different collections,
  so confirm the actual `Min`, groups, candidate pruning/exhaustion and elapsed pauses in logs.
- Reducing `MaxGCPauseMillis` usually selects smaller young/CSet work and therefore more frequent
  pauses; fixed per-pause work can raise total overhead and reduce throughput. Magnitude is
  workload/policy dependent, so predict direction, then measure pause distribution, frequency,
  total STW/concurrent CPU and throughput.
- Do not present the linear cost model as how G1 decides. It is a starting point for
  sizing; the real policy is an adaptive predictor over truncated histories of past
  measurements, recalibrating every collection.
- Every mixed collection is logged as `Pause Young (Mixed)`, never as a bare
  `Pause Mixed`, and `Pause Young (Prepare Mixed)` is the young-only collection that
  precedes the first one. A parser that reads the type immediately after `Pause `
  classifies all of them as young; one that matches `Mixed)` counts the preparation
  pause as mixed. Match `Pause Young \(Mixed\)` exactly.
- `Old regions: 50->55` has **no** third parenthesised number, unlike Eden and Survivor.
  A regex demanding `(\d+)->(\d+)\((\d+)\)` matches nothing and yields an old-growth
  estimate of zero with no error. Even a parsed positive delta is region growth, not an
  exact promoted-byte counter.
- `sorted(data)[int(len(data)*0.99)]` silently chooses one zero-based convention and is off by one
  from the common nearest-rank definition (`sorted[ceil(p × n)-1]`). For fewer than 100 samples,
  nearest-rank p99 is legitimately the maximum and extremely uncertain. Declare the quantile
  estimator, minimum sample count and confidence/error; prefer histogram/library aggregation over
  ad hoc indexing.
- Correlate SLO violations with the GC event **type**, not merely with the presence of
  GC. Alignment isolated to `Pause Young (Mixed)` prioritizes CSet/old-region phase analysis, but
  heap/live-set pressure may be why the set exists; correlation routes the investigation rather
  than proving one flag is causal.

## Change safety and rollback

Change one mechanism per canary when possible and persist the exact JVM command line, JDK
vendor/update, container limits and workload fingerprint. Define abort thresholds for full GC,
evacuation failure, allocation stall, application CPU/throughput and tail latency; keep the prior
configuration deployable. Experimental flags are not portable contracts—verify availability and
defaults during each JDK upgrade. Rotate and protect verbose logs as production telemetry.

## References

- [Flag reference and workload baselines](references/flags-and-baselines.md) — every
  flag with its JDK 25 default, whether it needs unlocking, and the trade-off it implies,
  plus three complete starting configurations with a per-flag justification for that
  workload. Read when choosing a value or when reviewing an existing command line.
- [Deriving values from an SLO](references/derivation.md) — the pause, young size,
  interval, overhead, IHOP and mixed-cost approximations with implementation boundaries, a fully
  worked case, and the measurement and calibration protocol. Read when turning measured
  rates into flag values, or when validating that a change produced the predicted effect.
- [The policy log and the symptom table](references/policy-log-and-troubleshooting.md) —
  the log lines that show what G1 decided and why, the symptom → cause → measure →
  lever table for young, mixed, marking, evacuation-failure and overhead problems, and
  the version notes that change a derivation. Read when a flag change did not produce
  the predicted effect, or before picking a lever.

Attribution

robsonkadesrobsonkades
View sourceMore from robsonkades →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →