Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
test_pipe_cache_pressure.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
27
28#include <stdarg.h>
29#include <stddef.h>
30// cmocka.h declares `extern jmp_buf global_expect_assert_env' at file scope without including
31// <setjmp.h> itself. Same suppression as test_pipe_cache_policy.c, and for the same reason.
32#include <setjmp.h> // NOLINT(misc-include-cleaner)
33#include <stdint.h>
34#include <cmocka.h>
35
36#define GIB ((size_t)1024 * 1024 * 1024)
37#define MIB ((size_t)1024 * 1024)
38
45
47static void _starts_at_the_plan(void **state)
48{
49 (void)state;
51
52 assert_int_equal(dt_pixelpipe_cache_pressure_budget(&p), 16 * GIB);
53 assert_int_equal(dt_pixelpipe_cache_pressure_cap(&p), 16 * GIB);
54 assert_int_equal(dt_pixelpipe_cache_pressure_reported(&p, 4 * GIB), 16 * GIB);
55}
56
59{
60 (void)state;
62
63 assert_int_equal(dt_pixelpipe_cache_pressure_shed_target(&p, 0.12, 8 * GIB), 6 * GIB);
64 assert_int_equal(dt_pixelpipe_cache_pressure_shed_target(&p, 0.40, 8 * GIB), 4 * GIB);
65
66 // Under the threshold nothing is shed, however much is held.
67 assert_int_equal(dt_pixelpipe_cache_pressure_shed_target(&p, 0.05, 8 * GIB),
69}
70
75{
76 (void)state;
78
82
83 // Nothing was shed, so nothing lowered the budget either.
84 assert_int_equal(dt_pixelpipe_cache_pressure_budget(&p), 16 * GIB);
85 assert_int_equal(p.mark, dt_pixelpipe_cache_pressure_mark_top(&p));
86}
87
90{
91 (void)state;
93
95 assert_int_equal(p.mark, 12 * GIB);
96 assert_int_equal(dt_pixelpipe_cache_pressure_budget(&p), 9 * GIB);
97
98 // Entries in use can leave the footprint above the ceiling; the ceiling only falls.
100 assert_int_equal(dt_pixelpipe_cache_pressure_budget(&p), 9 * GIB);
101}
102
113
119{
120 (void)state;
123
124 // The ceiling climbs, but never past 7/8 of the mark ...
125 for(int window = 0; window < 16; window++)
126 {
128 assert_true(p.ceiling <= dt_pixelpipe_cache_pressure_cap(&p));
129 }
130 assert_true(dt_pixelpipe_cache_pressure_budget(&p) < 12 * GIB);
131
132 // ... and the mark rises far more slowly than the ceiling: the 1/1024 of a plan per 2 s
133 // window is minutes of calm before the size that stalled is offered again.
134 assert_true(p.mark < 13 * GIB);
135}
136
140{
141 (void)state;
144
145 size_t previous = dt_pixelpipe_cache_pressure_budget(&p);
146 const size_t step = p.plan / 32;
147 for(int window = 0; window < 4096; window++)
148 {
149 if(!dt_pixelpipe_cache_pressure_relax(&p)) continue;
150 const size_t now = dt_pixelpipe_cache_pressure_budget(&p);
151 assert_true(now >= previous);
152 assert_true(now - previous <= step);
153 previous = now;
154 }
155 assert_int_equal(dt_pixelpipe_cache_pressure_budget(&p), 16 * GIB);
156}
157
161{
162 (void)state;
165
166 const size_t held = 11 * GIB; // still pinned by a running pipe
167 assert_true(dt_pixelpipe_cache_pressure_budget(&p) < held);
168 assert_int_equal(dt_pixelpipe_cache_pressure_reported(&p, held), held);
169}
170
171int main(void)
172{
173 const struct CMUnitTest tests[] = {
174 cmocka_unit_test(_starts_at_the_plan),
175 cmocka_unit_test(_sheds_a_share_of_what_is_held),
176 cmocka_unit_test(_an_empty_cache_is_not_the_cause),
179 cmocka_unit_test(_recovery_waits_under_the_mark),
182 };
183 return cmocka_run_group_tests(tests, NULL, NULL);
184}
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
GtkWidget * window
#define DT_PIXELPIPE_CACHE_PRESSURE_KEEP
static size_t dt_pixelpipe_cache_pressure_cap(const dt_pixelpipe_cache_pressure_t *p)
static size_t dt_pixelpipe_cache_pressure_shed_target(const dt_pixelpipe_cache_pressure_t *p, const double share, const size_t current)
static void dt_pixelpipe_cache_pressure_after_shed(dt_pixelpipe_cache_pressure_t *p, const size_t before, const size_t after)
static gboolean dt_pixelpipe_cache_pressure_relax(dt_pixelpipe_cache_pressure_t *p)
static void dt_pixelpipe_cache_pressure_init(dt_pixelpipe_cache_pressure_t *p, const size_t plan)
static size_t dt_pixelpipe_cache_pressure_reported(const dt_pixelpipe_cache_pressure_t *p, const size_t current)
static size_t dt_pixelpipe_cache_pressure_floor(const dt_pixelpipe_cache_pressure_t *p)
static size_t dt_pixelpipe_cache_pressure_mark_top(const dt_pixelpipe_cache_pressure_t *p)
static size_t dt_pixelpipe_cache_pressure_budget(const dt_pixelpipe_cache_pressure_t *p)
const float uint32_t state[4]
static void _recovery_reaches_the_plan_without_a_jump(void **state)
static void _the_budget_never_falls_under_the_floor(void **state)
static void _reported_budget_never_underflows_its_readers(void **state)
static void _a_shed_lowers_the_budget_to_what_is_left(void **state)
static void _an_empty_cache_is_not_the_cause(void **state)
int main(void)
static dt_pixelpipe_cache_pressure_t _plan_of(const size_t plan)
#define GIB
static void _recovery_waits_under_the_mark(void **state)
static void _starts_at_the_plan(void **state)
static void _sheds_a_share_of_what_is_held(void **state)