[Mesa-dev] [RFC 20/20] mesa: binary cache size management
Tapani Pälli
tapani.palli at intel.com
Mon Jun 2 05:06:01 PDT 2014
Patch adds validation round whenever cache path is created/checked.
Validation keeps the cache size at wanted level by deleting rarely
accessed file entries.
Signed-off-by: Tapani Pälli <tapani.palli at intel.com>
---
src/mesa/program/prog_diskcache.c | 97 +++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/src/mesa/program/prog_diskcache.c b/src/mesa/program/prog_diskcache.c
index f6087f7..568ec5b 100644
--- a/src/mesa/program/prog_diskcache.c
+++ b/src/mesa/program/prog_diskcache.c
@@ -26,6 +26,99 @@
#include "shader_cache.h"
#include "prog_diskcache.h"
+#ifndef _WIN32
+#include <dirent.h>
+
+#define MAX_CACHE_SIZE 100 * 1024 * 1024
+
+struct dir_entry_t
+{
+ char *path;
+ struct stat info;
+};
+
+
+static int
+sort_by_access_time(const void *_a, const void *_b)
+{
+ /* Compare access time of 2 entries */
+ struct dir_entry_t *a = (struct dir_entry_t *) _a;
+ struct dir_entry_t *b = (struct dir_entry_t *) _b;
+
+ if (a->info.st_atime > b->info.st_atime)
+ return 1;
+ return -1;
+}
+
+
+static int
+valid_cache_entry(const struct dirent *entry)
+{
+ /* Only regular files are possible valid cache entries. */
+ if (entry->d_type == DT_REG)
+ return 1;
+ return 0;
+}
+
+
+/**
+ * Cache size management. If cache size exceeds max_cache_size,
+ * entries are sorted by access time and oldest entries deleted
+ * until we fit.
+ */
+static void
+manage_cache_size(const char *path, const unsigned max_cache_size)
+{
+ struct dirent **entries;
+ int n = scandir(path, &entries, valid_cache_entry, NULL);
+
+ if (n <= 0)
+ return;
+
+ struct dir_entry_t *cache = NULL;
+ unsigned cache_size = 0;
+ unsigned cache_entries = 0;
+
+ void *mem_ctx = ralloc_context(NULL);
+
+ cache = ralloc_array(mem_ctx, struct dir_entry_t, n);
+
+ /* Construct entries with path and access information + calculate
+ * total size used by entries.
+ */
+ while (n--) {
+ cache[cache_entries].path =
+ ralloc_asprintf(mem_ctx, "%s/%s", path, entries[n]->d_name);
+ stat(cache[cache_entries].path, &cache[cache_entries].info);
+
+ cache_size += cache[cache_entries].info.st_size;
+
+ cache_entries++;
+ free(entries[n]);
+ }
+ free(entries);
+
+ /* No need to manage if we fit the max size. */
+ if (cache_size < max_cache_size)
+ goto free_allocated_memory;
+
+ /* Sort oldest first so we can 'delete until cache size less than max'. */
+ qsort(cache, cache_entries, sizeof(struct dir_entry_t), sort_by_access_time);
+
+ unsigned i = 0;
+ while (cache_size > max_cache_size && i < cache_entries) {
+ unlink(cache[i].path);
+ cache_size -= cache[i].info.st_size;
+ i++;
+ }
+
+free_allocated_memory:
+
+ ralloc_free(mem_ctx);
+}
+#endif
+
+
static int
mesa_mkdir_cache(const char *path)
{
@@ -72,6 +165,10 @@ mesa_program_diskcache_init(struct gl_context *ctx)
struct stat stat_info;
if (stat(ctx->BinaryCachePath, &stat_info) != 0)
result = mesa_mkdir_cache(ctx->BinaryCachePath);
+#ifndef _WIN32
+ else
+ manage_cache_size(ctx->BinaryCachePath, MAX_CACHE_SIZE);
+#endif
if (result == 0)
ctx->BinaryCacheActive = true;
--
1.8.3.1
More information about the mesa-dev
mailing list