@@ -266,6 +266,33 @@ func TestHistogramLoadFromCheckpointReturnsErrorOnNilInput(t *testing.T) {
266
266
}
267
267
268
268
func TestHistogramIsNotEmptyAfterSavingAndLoadingCheckpointsWithBoundaryValues (t * testing.T ) {
269
+ // There is a specific scenario in which the weights of the minimum and maximum histogram buckets,
270
+ // when saved to a VPACheckpoint and subsequently loaded, result in diminished weights for the minimum buckets.
271
+
272
+ // This issue arises due to rounding errors when converting float weights to integers in the VPACheckpoint.
273
+ // For instance, consider the weights:
274
+ // `w1` which approximates but is slightly larger than or equal to `epsilon`,
275
+ // `w2` which approximates but is slightly smaller than or equal to (`MaxCheckpointWeight` * `epsilon`) - `epsilon`.
276
+
277
+ // When these weights are stored in a VPACheckpoint, they are translated to integers:
278
+ // `w1` rounds to `1` (`wi1`),
279
+ // `w2` rounds to `MaxCheckpointWeight` (`wi2`).
280
+
281
+ // Upon loading from the VPACheckpoint, the histogram reconstructs its weights using a calculated ratio,
282
+ // aimed at reverting integer weights back to float values. This ratio is derived from:
283
+ // (`w1` + `w2`) / (`wi1` + `wi2`)
284
+ // Reference: https://github.com/plkokanov/autoscaler/blob/2aba67154cd4f117da4702b60a10c38c0651e659/vertical-pod-autoscaler/pkg/recommender/util/histogram.go#L256-L269
285
+
286
+ // Given the maximum potential values for `w1`, `w2`, `wi1` and `wi2` we arrive at:
287
+ // (`epsilon` + `MaxCheckpointWeight` * `epsilon` - `epsilon`) / (1 + MaxCheckpointWeight) = epsilon * `MaxCheckpointWeight` / (1 + MaxCheckpointWeight)
288
+
289
+ // Consequently, the maximum value for this ratio is less than `epsilon`, implying that when `w1`,
290
+ // initially scaled to `1`, is adjusted by this ratio, its recalculated weight falls short of `epsilon`.
291
+ // The same behavior can be observed when there are more than two weights.
292
+
293
+ // This test ensures that in such cases the histogram does not become empty.
294
+ // For more information check https://github.com/kubernetes/autoscaler/issues/7726
295
+
269
296
histogram := NewHistogram (testHistogramOptions )
270
297
histogram .AddSample (1 , weightEpsilon , anyTime )
271
298
histogram .AddSample (2 , (float64 (MaxCheckpointWeight )* weightEpsilon - weightEpsilon ), anyTime )
0 commit comments