Use shorter cache keys
This commit is contained in:
parent
ca3c49099f
commit
35f3312a1e
@ -24,6 +24,42 @@ PyTypeObject GraphicsManager_Type;
|
|||||||
|
|
||||||
#define DEFAULT_STORAGE_LIMIT 320u * (1024u * 1024u)
|
#define DEFAULT_STORAGE_LIMIT 320u * (1024u * 1024u)
|
||||||
#define REPORT_ERROR(...) { log_error(__VA_ARGS__); }
|
#define REPORT_ERROR(...) { log_error(__VA_ARGS__); }
|
||||||
|
#define CACHE_KEY_BUFFER_SIZE 32
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
cache_key(const ImageAndFrame x, char *key) {
|
||||||
|
if (x.frame_idx) return snprintf(key, CACHE_KEY_BUFFER_SIZE, "%llx:%x", x.image_id, x.frame_idx);
|
||||||
|
return snprintf(key, CACHE_KEY_BUFFER_SIZE, "%llx:", x.image_id);
|
||||||
|
}
|
||||||
|
#define CK(x) key, cache_key(x, key)
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
add_to_cache(GraphicsManager *self, const ImageAndFrame x, const void *data, const size_t sz) {
|
||||||
|
char key[CACHE_KEY_BUFFER_SIZE];
|
||||||
|
return add_to_disk_cache(self->disk_cache, CK(x), data, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
remove_from_cache(GraphicsManager *self, const ImageAndFrame x) {
|
||||||
|
char key[CACHE_KEY_BUFFER_SIZE];
|
||||||
|
return remove_from_disk_cache(self->disk_cache, CK(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PyObject*
|
||||||
|
read_from_cache_python(const GraphicsManager *self, const ImageAndFrame x) {
|
||||||
|
char key[CACHE_KEY_BUFFER_SIZE];
|
||||||
|
return read_from_disk_cache_python(self->disk_cache, CK(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
read_from_cache(const GraphicsManager *self, const ImageAndFrame x, void **data, size_t *sz) {
|
||||||
|
char key[CACHE_KEY_BUFFER_SIZE];
|
||||||
|
return read_from_disk_cache_simple(self->disk_cache, CK(x), data, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
cache_size(const GraphicsManager *self) { return disk_cache_total_size(self->disk_cache); }
|
||||||
|
#undef CK
|
||||||
|
|
||||||
|
|
||||||
static bool send_to_gpu = true;
|
static bool send_to_gpu = true;
|
||||||
@ -62,9 +98,7 @@ free_image(GraphicsManager *self, Image *img) {
|
|||||||
if (img->texture_id) free_texture(&img->texture_id);
|
if (img->texture_id) free_texture(&img->texture_id);
|
||||||
ImageAndFrame key = { .image_id=img->internal_id };
|
ImageAndFrame key = { .image_id=img->internal_id };
|
||||||
for (key.frame_idx = 0; key.frame_idx <= img->extra_framecnt; key.frame_idx++) {
|
for (key.frame_idx = 0; key.frame_idx <= img->extra_framecnt; key.frame_idx++) {
|
||||||
if (!remove_from_disk_cache(self->disk_cache, &key, sizeof(key))) {
|
if (!remove_from_cache(self, key) && PyErr_Occurred()) PyErr_Print();
|
||||||
if (PyErr_Occurred()) PyErr_Print();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (img->extra_frames) {
|
if (img->extra_frames) {
|
||||||
free(img->extra_frames);
|
free(img->extra_frames);
|
||||||
@ -544,8 +578,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
|
|||||||
if (send_to_gpu) {
|
if (send_to_gpu) {
|
||||||
send_image_to_gpu(&img->texture_id, img->load_data.data, img->width, img->height, img->is_opaque, img->is_4byte_aligned, false, REPEAT_CLAMP);
|
send_image_to_gpu(&img->texture_id, img->load_data.data, img->width, img->height, img->is_opaque, img->is_4byte_aligned, false, REPEAT_CLAMP);
|
||||||
}
|
}
|
||||||
ImageAndFrame key = {.image_id = img->internal_id};
|
if (!add_to_cache(self, (const ImageAndFrame){.image_id = img->internal_id}, img->load_data.data, img->load_data.data_sz)) {
|
||||||
if (!add_to_disk_cache(self->disk_cache, &key, sizeof(key), img->load_data.data, img->load_data.data_sz)) {
|
|
||||||
if (PyErr_Occurred()) PyErr_Print();
|
if (PyErr_Occurred()) PyErr_Print();
|
||||||
ABRT("ENOSPC", "Failed to store image data in disk cache");
|
ABRT("ENOSPC", "Failed to store image data in disk cache");
|
||||||
}
|
}
|
||||||
@ -961,9 +994,9 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
FAIL("EINVAL", "Data type for frames must match that of the base image");
|
FAIL("EINVAL", "Data type for frames must match that of the base image");
|
||||||
if (img->load_data.data_sz < bytes_per_pixel * data_width * data_height)
|
if (img->load_data.data_sz < bytes_per_pixel * data_width * data_height)
|
||||||
FAIL("ENODATA", "Insufficient image data %zu < %zu", img->load_data.data_sz, bytes_per_pixel * data_width, data_height);
|
FAIL("ENODATA", "Insufficient image data %zu < %zu", img->load_data.data_sz, bytes_per_pixel * data_width, data_height);
|
||||||
if (is_new_frame && disk_cache_total_size(self->disk_cache) + expected_data_sz > self->storage_limit * 5) {
|
if (is_new_frame && cache_size(self) + expected_data_sz > self->storage_limit * 5) {
|
||||||
remove_images(self, trim_predicate, img->internal_id);
|
remove_images(self, trim_predicate, img->internal_id);
|
||||||
if (is_new_frame && disk_cache_total_size(self->disk_cache) + expected_data_sz > self->storage_limit * 5)
|
if (is_new_frame && cache_size(self) + expected_data_sz > self->storage_limit * 5)
|
||||||
FAIL("ENOSPC", "Cache size exceeded cannot add new frames");
|
FAIL("ENOSPC", "Cache size exceeded cannot add new frames");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,7 +1005,7 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
if (is_new_frame) {
|
if (is_new_frame) {
|
||||||
if (g->num_cells) {
|
if (g->num_cells) {
|
||||||
ImageAndFrame other = { .image_id = img->internal_id, .frame_idx = g->num_cells - 1 };
|
ImageAndFrame other = { .image_id = img->internal_id, .frame_idx = g->num_cells - 1 };
|
||||||
if (!read_from_disk_cache_simple(self->disk_cache, &other, sizeof(other), &base_data, &data_sz)) {
|
if (!read_from_cache(self, other, &base_data, &data_sz)) {
|
||||||
FAIL("ENODATA", "No data for frame with number: %u found in image: %u", g->num_cells, img->client_id);
|
FAIL("ENODATA", "No data for frame with number: %u found in image: %u", g->num_cells, img->client_id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -981,7 +1014,7 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
data_sz = expected_data_sz;
|
data_sz = expected_data_sz;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!read_from_disk_cache_simple(self->disk_cache, &key, sizeof(key), &base_data, &data_sz)) {
|
if (!read_from_cache(self, key, &base_data, &data_sz)) {
|
||||||
FAIL("ENODATA", "No data for frame with number: %u found in image: %u", frame_number, img->client_id);
|
FAIL("ENODATA", "No data for frame with number: %u found in image: %u", frame_number, img->client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1005,7 +1038,7 @@ handle_animation_frame_load_command(GraphicsManager *self, GraphicsCommand *g, I
|
|||||||
#undef FAIL
|
#undef FAIL
|
||||||
|
|
||||||
free_load_data(&img->load_data);
|
free_load_data(&img->load_data);
|
||||||
bool added = add_to_disk_cache(self->disk_cache, &key, sizeof(key), base_data, data_sz);
|
bool added = add_to_cache(self, key, base_data, data_sz);
|
||||||
free(base_data);
|
free(base_data);
|
||||||
if (!added) {
|
if (!added) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
@ -1132,7 +1165,8 @@ image_as_dict(GraphicsManager *self, Image *img) {
|
|||||||
for (unsigned i = 0; i < img->extra_framecnt; i++) {
|
for (unsigned i = 0; i < img->extra_framecnt; i++) {
|
||||||
key.frame_idx = i + 1;
|
key.frame_idx = i + 1;
|
||||||
PyTuple_SET_ITEM(frames, i, Py_BuildValue(
|
PyTuple_SET_ITEM(frames, i, Py_BuildValue(
|
||||||
"{sI sN}", "gap", img->extra_frames[i].gap, "data", read_from_disk_cache_python(self->disk_cache, &key, sizeof(key))));
|
"{sI sN}", "gap", img->extra_frames[i].gap, "data", read_from_cache_python(self, key)));
|
||||||
|
if (PyErr_Occurred()) return NULL;
|
||||||
}
|
}
|
||||||
key.frame_idx = 0;
|
key.frame_idx = 0;
|
||||||
return Py_BuildValue("{sI sI sI sI sK sI sI sO sO sI sI sO sN sN}",
|
return Py_BuildValue("{sI sI sI sI sK sI sI sO sO sI sI sO sN sN}",
|
||||||
@ -1141,7 +1175,7 @@ image_as_dict(GraphicsManager *self, Image *img) {
|
|||||||
"is_4byte_aligned", img->is_4byte_aligned ? Py_True : Py_False,
|
"is_4byte_aligned", img->is_4byte_aligned ? Py_True : Py_False,
|
||||||
U(current_frame_index), U(loop_delay),
|
U(current_frame_index), U(loop_delay),
|
||||||
"animation_enabled", img->animation_enabled ? Py_True : Py_False,
|
"animation_enabled", img->animation_enabled ? Py_True : Py_False,
|
||||||
"data", read_from_disk_cache_python(self->disk_cache, &key, sizeof(key)),
|
"data", read_from_cache_python(self, key),
|
||||||
"extra_frames", frames
|
"extra_frames", frames
|
||||||
);
|
);
|
||||||
#undef U
|
#undef U
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
#include "monotonic.h"
|
#include "monotonic.h"
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char action, transmission_type, compressed, delete_action;
|
unsigned char action, transmission_type, compressed, delete_action;
|
||||||
@ -82,8 +81,6 @@ typedef struct {
|
|||||||
id_type image_id;
|
id_type image_id;
|
||||||
uint32_t frame_idx;
|
uint32_t frame_idx;
|
||||||
} ImageAndFrame;
|
} ImageAndFrame;
|
||||||
static_assert(sizeof(ImageAndFrame) != sizeof(id_type) + sizeof(uint32_t),
|
|
||||||
"Padding not allowed in ImageAndFrame because it is used as a cache key and padding is un-initialized");
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|||||||
@ -612,6 +612,8 @@ class TestGraphics(BaseTest):
|
|||||||
|
|
||||||
# simple new frame
|
# simple new frame
|
||||||
t(payload='2' * 36)
|
t(payload='2' * 36)
|
||||||
|
img = g.image_for_client_id(1)
|
||||||
|
self.assertEqual(img['extra_frames'], ({'gap': 40, 'data': b'2' * 36},))
|
||||||
|
|
||||||
# self.ae(g.image_count, 0)
|
# self.ae(g.image_count, 0)
|
||||||
# self.assertEqual(g.disk_cache.total_size, 0)
|
# self.assertEqual(g.disk_cache.total_size, 0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user