Make high level cache, low level cache and image cache all be initialised from passed parameters

Calculate all cache sizes from single memory cache size option and sanity check
have a single global struct to hold all parameters instead of several individual variables

svn path=/trunk/netsurf/; revision=12784
This commit is contained in:
Vincent Sanders 2011-09-10 00:55:39 +00:00
parent cbeffd4c5f
commit 2d33a8f85a
5 changed files with 161 additions and 114 deletions

View File

@ -84,6 +84,8 @@ struct hlcache_s {
hlcache_retrieval_ctx *retrieval_ctx_ring; hlcache_retrieval_ctx *retrieval_ctx_ring;
/* statsistics */ /* statsistics */
unsigned int hit_count;
unsigned int miss_count;
}; };
/** high level cache state */ /** high level cache state */
@ -118,7 +120,8 @@ hlcache_initialise(const struct hlcache_parameters *hlcache_parameters)
} }
ret = llcache_initialise(hlcache_parameters->cb, ret = llcache_initialise(hlcache_parameters->cb,
hlcache_parameters->cb_ctx); hlcache_parameters->cb_ctx,
hlcache_parameters->limit);
if (ret != NSERROR_OK) { if (ret != NSERROR_OK) {
free(hlcache); free(hlcache);
hlcache = NULL; hlcache = NULL;
@ -203,9 +206,13 @@ void hlcache_finalise(void)
hlcache->retrieval_ctx_ring = NULL; hlcache->retrieval_ctx_ring = NULL;
} }
LOG(("hit/miss %d/%d", hlcache->hit_count, hlcache->miss_count));
free(hlcache); free(hlcache);
hlcache = NULL; hlcache = NULL;
LOG(("Finalising low-level cache"));
llcache_finalise();
} }
/* See hlcache.h for documentation */ /* See hlcache.h for documentation */
@ -727,9 +734,12 @@ nserror hlcache_find_content(hlcache_retrieval_ctx *ctx,
/* Signal to caller that we created a content */ /* Signal to caller that we created a content */
error = NSERROR_NEED_DATA; error = NSERROR_NEED_DATA;
hlcache->miss_count++;
} else { } else {
/* Found a suitable content: no longer need low-level handle */ /* Found a suitable content: no longer need low-level handle */
llcache_handle_release(ctx->llcache); llcache_handle_release(ctx->llcache);
hlcache->hit_count++;
} }
/* Associate handle with content */ /* Associate handle with content */
@ -801,4 +811,3 @@ void hlcache_content_callback(struct content *c, content_msg msg,
if (error != NSERROR_OK) if (error != NSERROR_OK)
LOG(("Error in callback: %d", error)); LOG(("Error in callback: %d", error));
} }

View File

@ -29,7 +29,6 @@
#include "content/fetch.h" #include "content/fetch.h"
#include "content/llcache.h" #include "content/llcache.h"
#include "content/urldb.h" #include "content/urldb.h"
#include "desktop/options.h"
#include "utils/log.h" #include "utils/log.h"
#include "utils/messages.h" #include "utils/messages.h"
#include "utils/url.h" #include "utils/url.h"
@ -142,15 +141,23 @@ struct llcache_object {
size_t num_headers; /**< Number of fetch headers */ size_t num_headers; /**< Number of fetch headers */
}; };
/** Handler for fetch-related queries */ struct llcache_s {
static llcache_query_callback query_cb; /** Handler for fetch-related queries */
/** Data for fetch-related query handler */ llcache_query_callback query_cb;
static void *query_cb_pw; /** Data for fetch-related query handler */
void *query_cb_pw;
/** Head of the low-level cached object list */ /** Head of the low-level cached object list */
static llcache_object *llcache_cached_objects; llcache_object *cached_objects;
/** Head of the low-level uncached object list */
static llcache_object *llcache_uncached_objects; /** Head of the low-level uncached object list */
llcache_object *uncached_objects;
uint32_t limit;
};
/** low level cache state */
static struct llcache_s *llcache = NULL;
static nserror llcache_object_user_new(llcache_handle_callback cb, void *pw, static nserror llcache_object_user_new(llcache_handle_callback cb, void *pw,
llcache_object_user **user); llcache_object_user **user);
@ -246,10 +253,19 @@ static inline void llcache_invalidate_cache_control_data(llcache_object *object)
******************************************************************************/ ******************************************************************************/
/* See llcache.h for documentation */ /* See llcache.h for documentation */
nserror llcache_initialise(llcache_query_callback cb, void *pw) nserror
llcache_initialise(llcache_query_callback cb, void *pw, uint32_t llcache_limit)
{ {
query_cb = cb; llcache = calloc(1, sizeof(struct llcache_s));
query_cb_pw = pw; if (llcache == NULL) {
return NSERROR_NOMEM;
}
llcache->query_cb = cb;
llcache->query_cb_pw = pw;
llcache->limit = llcache_limit;
LOG(("llcache initialised with a limit of %d bytes", llcache_limit));
return NSERROR_OK; return NSERROR_OK;
} }
@ -260,7 +276,7 @@ void llcache_finalise(void)
llcache_object *object, *next; llcache_object *object, *next;
/* Clean uncached objects */ /* Clean uncached objects */
for (object = llcache_uncached_objects; object != NULL; object = next) { for (object = llcache->uncached_objects; object != NULL; object = next) {
llcache_object_user *user, *next_user; llcache_object_user *user, *next_user;
next = object->next; next = object->next;
@ -281,7 +297,7 @@ void llcache_finalise(void)
} }
/* Clean cached objects */ /* Clean cached objects */
for (object = llcache_cached_objects; object != NULL; object = next) { for (object = llcache->cached_objects; object != NULL; object = next) {
llcache_object_user *user, *next_user; llcache_object_user *user, *next_user;
next = object->next; next = object->next;
@ -300,6 +316,9 @@ void llcache_finalise(void)
llcache_object_destroy(object); llcache_object_destroy(object);
} }
free(llcache);
llcache = NULL;
} }
/* See llcache.h for documentation */ /* See llcache.h for documentation */
@ -310,12 +329,12 @@ nserror llcache_poll(void)
fetch_poll(); fetch_poll();
/* Catch new users up with state of objects */ /* Catch new users up with state of objects */
for (object = llcache_cached_objects; object != NULL; for (object = llcache->cached_objects; object != NULL;
object = object->next) { object = object->next) {
llcache_object_notify_users(object); llcache_object_notify_users(object);
} }
for (object = llcache_uncached_objects; object != NULL; for (object = llcache->uncached_objects; object != NULL;
object = object->next) { object = object->next) {
llcache_object_notify_users(object); llcache_object_notify_users(object);
} }
@ -453,7 +472,7 @@ nserror llcache_handle_abort(llcache_handle *handle)
/* Add new object to uncached list */ /* Add new object to uncached list */
llcache_object_add_to_list(newobject, llcache_object_add_to_list(newobject,
&llcache_uncached_objects); &llcache->uncached_objects);
} else { } else {
/* We're the only user, so abort any fetch in progress */ /* We're the only user, so abort any fetch in progress */
if (object->fetch.fetch != NULL) { if (object->fetch.fetch != NULL) {
@ -481,10 +500,10 @@ nserror llcache_handle_force_stream(llcache_handle *handle)
return NSERROR_OK; return NSERROR_OK;
/* Forcibly uncache this object */ /* Forcibly uncache this object */
if (llcache_object_in_list(object, llcache_cached_objects)) { if (llcache_object_in_list(object, llcache->cached_objects)) {
llcache_object_remove_from_list(object, llcache_object_remove_from_list(object,
&llcache_cached_objects); &llcache->cached_objects);
llcache_object_add_to_list(object, &llcache_uncached_objects); llcache_object_add_to_list(object, &llcache->uncached_objects);
} }
object->fetch.flags |= LLCACHE_RETRIEVE_STREAM_DATA; object->fetch.flags |= LLCACHE_RETRIEVE_STREAM_DATA;
@ -717,7 +736,7 @@ nserror llcache_object_retrieve(const char *url, uint32_t flags,
} }
/* Add new object to uncached list */ /* Add new object to uncached list */
llcache_object_add_to_list(obj, &llcache_uncached_objects); llcache_object_add_to_list(obj, &llcache->uncached_objects);
} else { } else {
error = llcache_object_retrieve_from_cache(defragmented_url, flags, referer, error = llcache_object_retrieve_from_cache(defragmented_url, flags, referer,
post, redirect_count, &obj); post, redirect_count, &obj);
@ -765,7 +784,7 @@ nserror llcache_object_retrieve_from_cache(const char *url, uint32_t flags,
#endif #endif
/* Search for the most recently fetched matching object */ /* Search for the most recently fetched matching object */
for (obj = llcache_cached_objects; obj != NULL; obj = obj->next) { for (obj = llcache->cached_objects; obj != NULL; obj = obj->next) {
bool match; bool match;
if ((newest == NULL || if ((newest == NULL ||
@ -821,7 +840,7 @@ nserror llcache_object_retrieve_from_cache(const char *url, uint32_t flags,
} }
/* Add new object to cache */ /* Add new object to cache */
llcache_object_add_to_list(obj, &llcache_cached_objects); llcache_object_add_to_list(obj, &llcache->cached_objects);
} else { } else {
/* No object found; create a new one */ /* No object found; create a new one */
/* Create new object */ /* Create new object */
@ -842,7 +861,7 @@ nserror llcache_object_retrieve_from_cache(const char *url, uint32_t flags,
} }
/* Add new object to cache */ /* Add new object to cache */
llcache_object_add_to_list(obj, &llcache_cached_objects); llcache_object_add_to_list(obj, &llcache->cached_objects);
} }
*result = obj; *result = obj;
@ -1643,7 +1662,7 @@ void llcache_clean(void)
*/ */
/* 1) Uncacheable objects with no users or fetches */ /* 1) Uncacheable objects with no users or fetches */
for (object = llcache_uncached_objects; object != NULL; object = next) { for (object = llcache->uncached_objects; object != NULL; object = next) {
next = object->next; next = object->next;
/* The candidate count of uncacheable objects is always 0 */ /* The candidate count of uncacheable objects is always 0 */
@ -1654,7 +1673,7 @@ void llcache_clean(void)
LOG(("Found victim %p", object)); LOG(("Found victim %p", object));
#endif #endif
llcache_object_remove_from_list(object, llcache_object_remove_from_list(object,
&llcache_uncached_objects); &llcache->uncached_objects);
llcache_object_destroy(object); llcache_object_destroy(object);
} else { } else {
llcache_size += object->source_len + sizeof(*object); llcache_size += object->source_len + sizeof(*object);
@ -1662,7 +1681,7 @@ void llcache_clean(void)
} }
/* 2) Stale cacheable objects with no users or pending fetches */ /* 2) Stale cacheable objects with no users or pending fetches */
for (object = llcache_cached_objects; object != NULL; object = next) { for (object = llcache->cached_objects; object != NULL; object = next) {
next = object->next; next = object->next;
if (object->users == NULL && object->candidate_count == 0 && if (object->users == NULL && object->candidate_count == 0 &&
@ -1673,17 +1692,17 @@ void llcache_clean(void)
LOG(("Found victim %p", object)); LOG(("Found victim %p", object));
#endif #endif
llcache_object_remove_from_list(object, llcache_object_remove_from_list(object,
&llcache_cached_objects); &llcache->cached_objects);
llcache_object_destroy(object); llcache_object_destroy(object);
} else { } else {
llcache_size += object->source_len + sizeof(*object); llcache_size += object->source_len + sizeof(*object);
} }
} }
if ((uint32_t) option_memory_cache_size < llcache_size) { if (llcache->limit < llcache_size) {
/* 3) Fresh cacheable objects with /* 3) Fresh cacheable objects with
* no users or pending fetches */ * no users or pending fetches */
for (object = llcache_cached_objects; object != NULL; for (object = llcache->cached_objects; object != NULL;
object = next) { object = next) {
next = object->next; next = object->next;
@ -1699,7 +1718,7 @@ void llcache_clean(void)
object->source_len + sizeof(*object); object->source_len + sizeof(*object);
llcache_object_remove_from_list(object, llcache_object_remove_from_list(object,
&llcache_cached_objects); &llcache->cached_objects);
llcache_object_destroy(object); llcache_object_destroy(object);
} }
} }
@ -2459,7 +2478,7 @@ nserror llcache_fetch_auth(llcache_object *object, const char *realm)
/* No authentication details, or tried what we had, so ask */ /* No authentication details, or tried what we had, so ask */
object->fetch.tried_with_auth = false; object->fetch.tried_with_auth = false;
if (query_cb != NULL) { if (llcache->query_cb != NULL) {
llcache_query query; llcache_query query;
/* Emit query for authentication details */ /* Emit query for authentication details */
@ -2469,7 +2488,7 @@ nserror llcache_fetch_auth(llcache_object *object, const char *realm)
object->fetch.outstanding_query = true; object->fetch.outstanding_query = true;
error = query_cb(&query, query_cb_pw, error = llcache->query_cb(&query, llcache->query_cb_pw,
llcache_query_handle_response, object); llcache_query_handle_response, object);
} else { } else {
llcache_event event; llcache_event event;
@ -2513,7 +2532,7 @@ nserror llcache_fetch_cert_error(llcache_object *object,
/* Invalidate cache-control data */ /* Invalidate cache-control data */
llcache_invalidate_cache_control_data(object); llcache_invalidate_cache_control_data(object);
if (query_cb != NULL) { if (llcache->query_cb != NULL) {
llcache_query query; llcache_query query;
/* Emit query for TLS */ /* Emit query for TLS */
@ -2524,7 +2543,7 @@ nserror llcache_fetch_cert_error(llcache_object *object,
object->fetch.outstanding_query = true; object->fetch.outstanding_query = true;
error = query_cb(&query, query_cb_pw, error = llcache->query_cb(&query, llcache->query_cb_pw,
llcache_query_handle_response, object); llcache_query_handle_response, object);
} else { } else {
llcache_event event; llcache_event event;

View File

@ -156,7 +156,7 @@ typedef nserror (*llcache_query_callback)(const llcache_query *query, void *pw,
* \param pw Pointer to query handler data * \param pw Pointer to query handler data
* \return NSERROR_OK on success, appropriate error otherwise. * \return NSERROR_OK on success, appropriate error otherwise.
*/ */
nserror llcache_initialise(llcache_query_callback cb, void *pw); nserror llcache_initialise(llcache_query_callback cb, void *pw, uint32_t llcache_limit);
/** /**
* Finalise the low-level cache * Finalise the low-level cache

View File

@ -70,7 +70,7 @@
/* the time between cache clean runs in ms */ /* the time between cache clean runs in ms */
#define IMAGE_CACHE_CLEAN_TIME (10 * 1000) #define IMAGE_CACHE_CLEAN_TIME (10 * 1000)
#define HL_CACHE_CLEAN_TIME (5 * 1000) #define HL_CACHE_CLEAN_TIME (2 * IMAGE_CACHE_CLEAN_TIME)
bool netsurf_quit = false; bool netsurf_quit = false;
bool verbose_log = false; bool verbose_log = false;
@ -109,6 +109,8 @@ static nserror netsurf_llcache_query_handler(const llcache_query *query,
return NSERROR_OK; return NSERROR_OK;
} }
#define MINIMUM_MEMORY_CACHE_SIZE (2 * 1024 * 1024)
/** /**
* Initialise components used by gui NetSurf. * Initialise components used by gui NetSurf.
*/ */
@ -127,8 +129,6 @@ nserror netsurf_init(int *pargc,
}; };
struct image_cache_parameters image_cache_parameters = { struct image_cache_parameters image_cache_parameters = {
.bg_clean_time = IMAGE_CACHE_CLEAN_TIME, .bg_clean_time = IMAGE_CACHE_CLEAN_TIME,
.limit = (8 * 1024 * 1024),
.hysteresis = (2 * 1024 * 1024),
.speculative_small = SPECULATE_SMALL .speculative_small = SPECULATE_SMALL
}; };
@ -169,6 +169,24 @@ nserror netsurf_init(int *pargc,
messages_load(messages); messages_load(messages);
/* set up cache limits based on the memory cache size option */
hlcache_parameters.limit = option_memory_cache_size;
if (hlcache_parameters.limit < MINIMUM_MEMORY_CACHE_SIZE) {
hlcache_parameters.limit = MINIMUM_MEMORY_CACHE_SIZE;
LOG(("Setting minimum memory cache size to %d",
hlcache_parameters.limit));
}
/* image cache is 25% of total memory cache size */
image_cache_parameters.limit = (hlcache_parameters.limit * 25) / 100;
/* image cache hysteresis is 20% of teh image cache size */
image_cache_parameters.hysteresis = (image_cache_parameters.limit * 20) / 100;
/* account for image cache use from total */
hlcache_parameters.limit -= image_cache_parameters.limit;
/* image handler bitmap cache */ /* image handler bitmap cache */
error = image_cache_init(&image_cache_parameters); error = image_cache_init(&image_cache_parameters);
if (error != NSERROR_OK) if (error != NSERROR_OK)
@ -244,9 +262,6 @@ void netsurf_exit(void)
LOG(("Finalising high-level cache")); LOG(("Finalising high-level cache"));
hlcache_finalise(); hlcache_finalise();
LOG(("Finalising low-level cache"));
llcache_finalise();
LOG(("Closing fetches")); LOG(("Closing fetches"));
fetch_quit(); fetch_quit();

View File

@ -89,20 +89,20 @@ struct image_cache_s {
/** Maximum count of bitmaps allocated at any one time */ /** Maximum count of bitmaps allocated at any one time */
int max_bitmap_count; int max_bitmap_count;
/** The size of the bitmaps when teh max count occoured */ /** The size of the bitmaps when the max count occoured */
size_t max_bitmap_count_size; size_t max_bitmap_count_size;
/** Bitmap was not available at plot time required conversion */ /** Bitmap was not available at plot time required conversion */
int miss_count; int miss_count;
size_t miss_size; uint64_t miss_size;
/** Bitmap was available at plot time required no conversion */ /** Bitmap was available at plot time required no conversion */
int hit_count; int hit_count;
size_t hit_size; uint64_t hit_size;
/** Bitmap was not available at plot time and required /** Bitmap was not available at plot time and required
* conversion which failed. * conversion which failed.
*/ */
int fail_count; int fail_count;
size_t fail_size; uint64_t fail_size;
/* Cache entry freed without ever being redrawn */ /* Cache entry freed without ever being redrawn */
int total_unrendered; int total_unrendered;
@ -120,6 +120,7 @@ struct image_cache_s {
unsigned int peak_conversions_size; unsigned int peak_conversions_size;
}; };
/** image cache state */
static struct image_cache_s *image_cache = NULL; static struct image_cache_s *image_cache = NULL;
@ -357,6 +358,9 @@ image_cache_init(const struct image_cache_parameters *image_cache_parameters)
image_cache__background_update, image_cache__background_update,
image_cache); image_cache);
LOG(("Image cache initilised with a limit of %d hysteresis of %d",
image_cache->params.limit, image_cache->params.hysteresis));
return NSERROR_OK; return NSERROR_OK;
} }