53 lines
2.6 KiB
Markdown
53 lines
2.6 KiB
Markdown
# PR#162: The gap filler of the metrics history has no loop, so its mutants no longer run out of memory
|
|
|
|
> **WARNING:** This document describes only the change applied in this PR.
|
|
> It may already be outdated once the next PR is merged.
|
|
> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.
|
|
|
|
## Problem
|
|
|
|
The nightly build `mutation` failed on main at `15b1251` after 32:45, in the gate `mutationCrapCheck`.
|
|
The gate refused to judge `HistoryTier.nulls(I)`: two of its four mutants ended with `MEMORY_ERROR`, which werkcrappit reports as `INCONCLUSIVE`.
|
|
The method is `List(size) { null }`, unchanged since PR#29.
|
|
Kotlin compiles it to a counting loop that fills an `ArrayList`.
|
|
PIT mutates the counter, the loop never ends, and the list grows.
|
|
Whether such a mutant first meets the PIT timeout (detected) or the heap limit (`MEMORY_ERROR`) depends on the load of the night.
|
|
On 2026-10-10 all four were killed; on 2026-10-14 two ran out of memory.
|
|
|
|
## Non-Goals
|
|
|
|
- No change to werkcrappit: whether a `MEMORY_ERROR` counts as detected stays its own decision.
|
|
- No change to the minions' heap or the PIT timeouts.
|
|
- No other method: the last report names no other `MEMORY_ERROR`.
|
|
|
|
## Specification
|
|
|
|
### Feature: the history fills a new series with nulls
|
|
|
|
#### Scenario#162.01: A series that appears later starts with one null per earlier point!
|
|
|
|
So that every column of a tier has as many points as the tier has timestamps.
|
|
|
|
- **Given** a sample tier with three points and no series `disk.hdd.usedGib`
|
|
- **When** a fourth sample has a value for that series
|
|
- **Then** the series is `null, null, null` and the new value
|
|
|
|
##### Verified by
|
|
|
|
- [MetricsHistoryUnitTest: every sample becomes one point of the sample tier, column-wise for all keys](../../src/test/kotlin/de/hoennig/werkator/metrics/MetricsHistoryUnitTest.kt)
|
|
|
|
## Solution
|
|
|
|
- `HistoryTier.nulls` builds its list as `arrayOfNulls<Double>(size).asList()`.
|
|
The bytecode has no loop for PIT to mutate into an endless one; the behaviour is the same.
|
|
- Measured locally with PIT on `HistoryTier` alone: `nulls` has one mutant instead of four, killed; complexity 1, Mutation-CRAP 1.00; no `INCONCLUSIVE`, the gate passes.
|
|
- A KDoc on the method says why, so nobody turns it back into `List(size) { null }`.
|
|
- Werkbaum: a node under `#tests`.
|
|
- Version 1.43.2, with an entry in the release notes.
|
|
|
|
## Open Questions
|
|
|
|
- [ ] TODO.werkcrappit: PIT counts `MEMORY_ERROR` as detected, werkcrappit as inconclusive.
|
|
Another mutant with an endless allocation would fail the gate the same way.
|
|
Whether werkcrappit should count it as detected is a decision in werkcrappit, not here.
|