Author: stefan2 Date: Mon Aug 9 18:14:01 2010 New Revision: 983760 URL: http://svn.apache.org/viewvc?rev=983760&view=rev Log: * subversion/libsvn_fs_fs/fs.h (fs_fs_data_t): add node_revision_cache member * subversion/libsvn_fs_fs/fs_fs.c (get_noderev_cache_key, get_cached_node_revision_body, set_cached_node_revision_body): new functions to get / set noderevs from / to cache (get_node_revision_body): speed up using the noderev cache * subversion/libsvn_fs_fs/caching.c (svn_fs_fs__initialize_caches): initialize the revnode cache; fix a comment
Modified: subversion/branches/performance/subversion/libsvn_fs_fs/caching.c subversion/branches/performance/subversion/libsvn_fs_fs/fs.h subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Modified: subversion/branches/performance/subversion/libsvn_fs_fs/caching.c URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/caching.c?rev=983760&r1=983759&r2=983760&view=diff ============================================================================== --- subversion/branches/performance/subversion/libsvn_fs_fs/caching.c (original) +++ subversion/branches/performance/subversion/libsvn_fs_fs/caching.c Mon Aug 9 18:14:01 2010 @@ -300,7 +300,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f /* initialize file handle cache as configured */ ffd->file_handle_cache = get_global_file_handle_cache(); - /* if enabled, enable the txdelta window cache */ + /* initialize txdelta window cache, if that has been enabled */ if (get_global_membuffer_cache() && svn_fs_fs__get_cache_config()->cache_txdeltas) { @@ -322,5 +322,28 @@ svn_fs_fs__initialize_caches(svn_fs_t *f SVN_ERR(svn_cache__set_error_handler(ffd->txdelta_window_cache, warn_on_cache_errors, fs, pool)); + /* initialize node revision cache, if caching has been enabled */ + if (get_global_membuffer_cache()) + { + SVN_ERR(svn_cache__create_membuffer_cache(&(ffd->node_revision_cache), + get_global_membuffer_cache(), + svn_fs_fs__serialize_node_revision, + svn_fs_fs__deserialize_node_revision, + APR_HASH_KEY_STRING, + apr_pstrcat(pool, + prefix, + "NODEREVS", + NULL), + fs->pool)); + } + else + { + ffd->node_revision_cache = NULL; + } + + if (ffd->node_revision_cache && ! no_handler) + SVN_ERR(svn_cache__set_error_handler(ffd->node_revision_cache, + warn_on_cache_errors, fs, pool)); + return SVN_NO_ERROR; } Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs.h URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs.h?rev=983760&r1=983759&r2=983760&view=diff ============================================================================== --- subversion/branches/performance/subversion/libsvn_fs_fs/fs.h (original) +++ subversion/branches/performance/subversion/libsvn_fs_fs/fs.h Mon Aug 9 18:14:01 2010 @@ -247,6 +247,9 @@ typedef struct /* Cache for txdelta_window_t objects; the key is (revFilePath, offset) */ svn_cache__t *txdelta_window_cache; + /* Cache for node_revision_t objects; the key is (revision, id offset) */ + svn_cache__t *node_revision_cache; + /* Data shared between all svn_fs_t objects for a given filesystem. */ fs_fs_shared_data_t *shared; Modified: subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c?rev=983760&r1=983759&r2=983760&view=diff ============================================================================== --- subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c (original) +++ subversion/branches/performance/subversion/libsvn_fs_fs/fs_fs.c Mon Aug 9 18:14:01 2010 @@ -2079,6 +2079,66 @@ read_rep_offsets(representation_t **rep_ return SVN_NO_ERROR; } +/* Combine the revision and offset of the ID to a string that will + * be used as a cache key. Allocations will be made from POOL. + */ +static const char * +get_noderev_cache_key(const svn_fs_id_t *id, apr_pool_t *pool) +{ + return svn_fs_fs__combine_two_numbers(svn_fs_fs__id_rev(id), + svn_fs_fs__id_offset(id), + pool); +} + +/* Look up the NODEREV_P for ID in FS' node revsion cache. If noderev + * caching has been enabled and the data can be found, IS_CACHED will + * be set to TRUE. The noderev will be allocated from POOL. + * + * Non-permanent ids (e.g. ids within a TXN) will not be cached. + */ +static svn_error_t * +get_cached_node_revision_body(node_revision_t **noderev_p, + svn_fs_t *fs, + const svn_fs_id_t *id, + svn_boolean_t *is_cached, + apr_pool_t *pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + if (! ffd->node_revision_cache || svn_fs_fs__id_txn_id(id)) + *is_cached = FALSE; + else + SVN_ERR(svn_cache__get((void **) noderev_p, + is_cached, + ffd->node_revision_cache, + get_noderev_cache_key(id, pool), + pool)); + + return SVN_NO_ERROR; +} + +/* If noderev caching has been enabled, store the NODEREV_P for the given ID + * in FS' node revsion cache. SCRATCH_POOL is used for temporary allcations. + * + * Non-permanent ids (e.g. ids within a TXN) will not be cached. + */ +static svn_error_t * +set_cached_node_revision_body(node_revision_t *noderev_p, + svn_fs_t *fs, + const svn_fs_id_t *id, + apr_pool_t *scratch_pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + + if (ffd->node_revision_cache && !svn_fs_fs__id_txn_id(id)) + return svn_cache__set(ffd->node_revision_cache, + get_noderev_cache_key(id, scratch_pool), + noderev_p, + scratch_pool); + + return SVN_NO_ERROR; +} + + /* Get the node-revision for the node ID in FS. Set *NODEREV_P to the new node-revision structure, allocated in POOL. See svn_fs_fs__get_node_revision, which wraps this and adds another @@ -2091,6 +2151,12 @@ get_node_revision_body(node_revision_t * { svn_file_handle_cache__handle_t *revision_file; svn_error_t *err; + svn_boolean_t is_cached = FALSE; + + /* First, try a cache lookup. If that succeeds, we are done here. */ + SVN_ERR(get_cached_node_revision_body(noderev_p, fs, id, &is_cached, pool)); + if (is_cached) + return SVN_NO_ERROR; if (svn_fs_fs__id_txn_id(id)) { @@ -2126,12 +2192,15 @@ get_node_revision_body(node_revision_t * return svn_error_return(err); } - return svn_fs_fs__read_noderev(noderev_p, - svn_stream__from_cached_file_handle - (revision_file, + SVN_ERR(svn_fs_fs__read_noderev(noderev_p, + svn_stream__from_cached_file_handle + (revision_file, FALSE, pool), - pool); + pool)); + + /* The noderev is not in cache, yet. Add it, if caching has been enabled. */ + return set_cached_node_revision_body(*noderev_p, fs, id, pool); } svn_error_t *