65 memset(
m->totals, 0,
sizeof(
m->totals));
79 const gint64 min_window_us)
81 if(
m->time_us != 0 && now -
m->time_us < min_window_us)
return -1.;
85 const gint64 elapsed = now -
m->time_us;
92 if(totals[
i] >=
m->totals[
i])
93 share =
MAX(share, (
double)(totals[
i] -
m->totals[
i]) / (
double)elapsed);
96 memcpy(
m->totals, totals,
sizeof(
m->totals));
107 const size_t before = sink->
held(sink->
user);
111 size_t given_back = 0;
112 const size_t after = sink->
shed(sink->
user, target, &given_back);
115 m->shed_time_us = g_get_monotonic_time();
117 const size_t freed = before - after;
119 "[pixelpipe_cache] kernel memory pressure (%s): %.0f%% of the window stalled -- shed %" G_GSIZE_FORMAT
120 " MiB of cache, returned %" G_GSIZE_FORMAT
" MiB to the OS, budget lowered to %" G_GSIZE_FORMAT
" MiB\n",
121 origin, 100. * share, freed / (1024 * 1024), given_back / (1024 * 1024),
136 const gint64 now = g_get_monotonic_time();
138 if(share < 0.)
return 0;
145 "[pixelpipe_cache] kernel memory pressure calm: budget raised to %" G_GSIZE_FORMAT
146 " MiB (at most %" G_GSIZE_FORMAT
" MiB until the pressure mark recovers)\n",
160 const gint64 now = g_get_monotonic_time();
168 void (*wake)(
void *user),
void *user)
177 "[pixelpipe_cache] watching kernel memory pressure on %i level(s)\n",
int levels(struct dt_imageio_module_data_t *data)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
int dt_memory_pressure_watch_levels(const dt_memory_pressure_watch_t *watch)
int dt_memory_pressure_read_full_stall(uint64_t *total_us, int max_levels)
void dt_memory_pressure_watch_stop(dt_memory_pressure_watch_t **watch)
dt_memory_pressure_watch_t * dt_memory_pressure_watch_start(uint64_t stall_us, uint64_t window_us, void(*stalled)(void *user), void *user)
#define DT_MEMORY_PRESSURE_MAX_LEVELS
static double _window_share(dt_pixelpipe_cache_pressure_monitor_t *m, const gint64 now, const gint64 min_window_us)
void dt_pixelpipe_cache_pressure_monitor_init(dt_pixelpipe_cache_pressure_monitor_t *m, const size_t plan)
void dt_pixelpipe_cache_pressure_triggered(dt_pixelpipe_cache_pressure_monitor_t *m, const dt_pixelpipe_cache_pressure_sink_t *sink)
static gboolean _shed_too_soon(const dt_pixelpipe_cache_pressure_monitor_t *m, const gint64 now)
static size_t _shed(dt_pixelpipe_cache_pressure_monitor_t *m, const dt_pixelpipe_cache_pressure_sink_t *sink, const double share, const char *origin)
void dt_pixelpipe_cache_pressure_watch_start(dt_pixelpipe_cache_pressure_monitor_t *m, void(*wake)(void *user), void *user)
size_t dt_pixelpipe_cache_pressure_react(dt_pixelpipe_cache_pressure_monitor_t *m, const dt_pixelpipe_cache_pressure_sink_t *sink)
void dt_pixelpipe_cache_pressure_watch_stop(dt_pixelpipe_cache_pressure_monitor_t *m)
#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)
#define DT_PIXELPIPE_CACHE_PSI_SHED
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)
#define DT_PIXELPIPE_CACHE_PSI_CALM
#define DT_PIXELPIPE_CACHE_PSI_WINDOW_US
static size_t dt_pixelpipe_cache_pressure_budget(const dt_pixelpipe_cache_pressure_t *p)
unsigned __int64 uint64_t
size_t(* shed)(void *user, size_t target, size_t *given_back)
size_t(* held)(void *user)