You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/06/23 11:45:20 UTC
svn commit: r1604726 -
/subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
Author: stsp
Date: Mon Jun 23 09:45:19 2014
New Revision: 1604726
URL: http://svn.apache.org/r1604726
Log:
Introduce scratch pools in the block_read() family of functions.
Resident memory size of 'svn log -v' drops from 317MB to 173MB while
showing r11708 of ruby's Subversion repository via ra_local (on OpenBSD).
Repository format used for testing was fsfs7 without default settings.
* subversion/libsvn_fs_fs/cached_data.c
(svn_fs_fs__get_changes): Rename 'pool' argument to 'result_pool'.
Create a local scratch pool and pass it down.
(init_rep_state): Rename 'pool' argument to 'result_pool'.
(block_read_windows, read_rep_header, block_read_contents,
block_read_changes, block_read_noderev): Switch to dual-pool
model (result/scratch pool), and pass a scratch pool where
possible (in particular, svn_cache__set()).
(block_read): Pass iterpool as scratch pool to block_read_*.
Modified:
subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
Modified: subversion/trunk/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/cached_data.c?rev=1604726&r1=1604725&r2=1604726&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/cached_data.c Mon Jun 23 09:45:19 2014
@@ -2639,19 +2639,20 @@ svn_error_t *
svn_fs_fs__get_changes(apr_array_header_t **changes,
svn_fs_t *fs,
svn_revnum_t rev,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
apr_off_t changes_offset = SVN_FS_FS__ITEM_INDEX_CHANGES;
svn_fs_fs__revision_file_t *revision_file;
svn_boolean_t found;
fs_fs_data_t *ffd = fs->fsap_data;
+ apr_pool_t *scratch_pool = svn_pool_create(result_pool);
/* try cache lookup first */
if (ffd->changes_cache)
{
SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
- &rev, pool));
+ &rev, result_pool));
}
else
{
@@ -2662,47 +2663,49 @@ svn_fs_fs__get_changes(apr_array_header_
{
/* read changes from revision file */
- SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool));
+ SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev,
- pool));
+ scratch_pool));
if (svn_fs_fs__use_log_addressing(fs, rev))
{
/* 'block-read' will also provide us with the desired data */
SVN_ERR(block_read((void **)changes, fs,
rev, SVN_FS_FS__ITEM_INDEX_CHANGES,
- revision_file, pool, pool));
+ revision_file, result_pool, scratch_pool));
}
else
{
/* physical addressing mode code path */
SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
revision_file->file, fs, rev,
- pool));
+ scratch_pool));
SVN_ERR(aligned_seek(fs, revision_file->file, NULL, changes_offset,
- pool));
+ scratch_pool));
SVN_ERR(svn_fs_fs__read_changes(changes, revision_file->stream,
- pool));
+ result_pool));
/* cache for future reference */
if (ffd->changes_cache)
- SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes, pool));
+ SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes,
+ scratch_pool));
}
SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
}
SVN_ERR(dbg_log_access(fs, rev, changes_offset, *changes,
- SVN_FS_FS__ITEM_TYPE_CHANGES, pool));
+ SVN_FS_FS__ITEM_TYPE_CHANGES, scratch_pool));
+ svn_pool_destroy(scratch_pool);
return SVN_NO_ERROR;
}
/* Inialize the representation read state RS for the given REP_HEADER and
* p2l index ENTRY. If not NULL, assign FILE and STREAM to RS.
- * Use POOL for allocations.
+ * Use RESULT_POOL for allocations.
*/
static svn_error_t *
init_rep_state(rep_state_t *rs,
@@ -2710,10 +2713,10 @@ init_rep_state(rep_state_t *rs,
svn_fs_t *fs,
svn_fs_fs__revision_file_t *file,
svn_fs_fs__p2l_entry_t* entry,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- shared_file_t *shared_file = apr_pcalloc(pool, sizeof(*shared_file));
+ shared_file_t *shared_file = apr_pcalloc(result_pool, sizeof(*shared_file));
/* this function does not apply to representation containers */
SVN_ERR_ASSERT(entry->type >= SVN_FS_FS__ITEM_TYPE_FILE_REP
@@ -2722,7 +2725,7 @@ init_rep_state(rep_state_t *rs,
shared_file->rfile = file;
shared_file->fs = fs;
shared_file->revision = entry->item.revision;
- shared_file->pool = pool;
+ shared_file->pool = result_pool;
rs->sfile = shared_file;
rs->revision = entry->item.revision;
@@ -2870,7 +2873,7 @@ cache_windows(svn_fs_t *fs,
/* Read all txdelta / plain windows following REP_HEADER in FS as described
* by ENTRY. Read the data from the already open FILE and the wrapping
* STREAM object. If MAX_OFFSET is not -1, don't read windows that start
- * at or beyond that offset. Use POOL for allocations.
+ * at or beyond that offset. Use SCRATCH_POOL for temporary allocations.
* If caching is not enabled, this is a no-op.
*/
static svn_error_t *
@@ -2879,7 +2882,8 @@ block_read_windows(svn_fs_fs__rep_header
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t* entry,
apr_off_t max_offset,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
rep_state_t rs = { 0 };
@@ -2892,7 +2896,8 @@ block_read_windows(svn_fs_fs__rep_header
&& !ffd->combined_window_cache))
return SVN_NO_ERROR;
- SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, pool));
+ SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry,
+ result_pool));
/* RS->FILE may be shared between RS instances -> make sure we point
* to the right data. */
@@ -2904,26 +2909,28 @@ block_read_windows(svn_fs_fs__rep_header
/* already in cache? */
SVN_ERR(svn_cache__has_key(&is_cached, rs.combined_cache,
- get_window_key(&key, &rs), pool));
+ get_window_key(&key, &rs),
+ scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
/* for larger reps, the header may have crossed a block boundary.
* make sure we still read blocks properly aligned, i.e. don't use
* plain seek here. */
- SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
+ SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, scratch_pool));
- plaintext = svn_stringbuf_create_ensure(rs.size, pool);
+ plaintext = svn_stringbuf_create_ensure(rs.size, result_pool);
SVN_ERR(svn_io_file_read_full2(rev_file->file, plaintext->data,
- rs.size, &plaintext->len, NULL, pool));
+ rs.size, &plaintext->len, NULL,
+ result_pool));
plaintext->data[plaintext->len] = 0;
rs.current += rs.size;
- SVN_ERR(set_cached_combined_window(plaintext, &rs, pool));
+ SVN_ERR(set_cached_combined_window(plaintext, &rs, scratch_pool));
}
else
{
- SVN_ERR(cache_windows(fs, &rs, max_offset, pool));
+ SVN_ERR(cache_windows(fs, &rs, max_offset, scratch_pool));
}
return SVN_NO_ERROR;
@@ -2939,7 +2946,8 @@ read_rep_header(svn_fs_fs__rep_header_t
svn_fs_t *fs,
svn_stream_t *stream,
pair_cache_key_t *key,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_boolean_t is_cached = FALSE;
@@ -2947,15 +2955,17 @@ read_rep_header(svn_fs_fs__rep_header_t
if (ffd->rep_header_cache)
{
SVN_ERR(svn_cache__get((void**)rep_header, &is_cached,
- ffd->rep_header_cache, key, pool));
+ ffd->rep_header_cache, key,
+ result_pool));
if (is_cached)
return SVN_NO_ERROR;
}
- SVN_ERR(svn_fs_fs__read_rep_header(rep_header, stream, pool));
+ SVN_ERR(svn_fs_fs__read_rep_header(rep_header, stream, result_pool));
if (ffd->rep_header_cache)
- SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header, pool));
+ SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -2964,14 +2974,16 @@ read_rep_header(svn_fs_fs__rep_header_t
* addressed by ENTRY->ITEM in FS and cache it if caches are enabled.
* Read the data from the already open FILE and the wrapping
* STREAM object. If MAX_OFFSET is not -1, don't read windows that start
- * at or beyond that offset. Use POOL for allocations.
+ * at or beyond that offset.
+ * Use SCRATCH_POOL for temporary allocations.
*/
static svn_error_t *
block_read_contents(svn_fs_t *fs,
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t* entry,
apr_off_t max_offset,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
pair_cache_key_t header_key = { 0 };
svn_fs_fs__rep_header_t *rep_header;
@@ -2980,9 +2992,9 @@ block_read_contents(svn_fs_t *fs,
header_key.second = entry->item.number;
SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
- pool));
+ result_pool, scratch_pool));
SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, max_offset,
- pool));
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3035,7 +3047,8 @@ block_read_changes(apr_array_header_t **
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t *entry,
svn_boolean_t must_read,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_stream_t *stream;
@@ -3047,22 +3060,24 @@ block_read_changes(apr_array_header_t **
{
svn_boolean_t is_cached;
SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache,
- &entry->item.revision, pool));
+ &entry->item.revision,
+ scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry,
+ scratch_pool));
/* read changes from revision file */
- SVN_ERR(svn_fs_fs__read_changes(changes, stream, pool));
+ SVN_ERR(svn_fs_fs__read_changes(changes, stream, result_pool));
/* cache for future reference */
if (ffd->changes_cache)
SVN_ERR(svn_cache__set(ffd->changes_cache, &entry->item.revision,
- *changes, pool));
+ *changes, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3070,7 +3085,7 @@ block_read_changes(apr_array_header_t **
/* If not already cached or if MUST_READ is set, read the nod revision
* addressed by ENTRY in FS and retúrn it in *NODEREV_P. Cache the
* result if caching is enabled. Read the data from the already open
- * FILE and wrapping FILE_STREAM. Use POOL for allocations.
+ * FILE and wrapping FILE_STREAM. Use SCRATCH_POOL for temporary allocations.
*/
static svn_error_t *
block_read_noderev(node_revision_t **noderev_p,
@@ -3078,7 +3093,8 @@ block_read_noderev(node_revision_t **nod
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t *entry,
svn_boolean_t must_read,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_stream_t *stream;
@@ -3095,23 +3111,24 @@ block_read_noderev(node_revision_t **nod
{
svn_boolean_t is_cached;
SVN_ERR(svn_cache__has_key(&is_cached, ffd->node_revision_cache,
- &key, pool));
+ &key, scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry,
+ scratch_pool));
/* read node rev from revision file */
- SVN_ERR(svn_fs_fs__read_noderev(noderev_p, stream, pool));
+ SVN_ERR(svn_fs_fs__read_noderev(noderev_p, stream, result_pool));
/* Workaround issue #4031: is-fresh-txn-root in revision files. */
(*noderev_p)->is_fresh_txn_root = FALSE;
if (ffd->node_revision_cache)
SVN_ERR(svn_cache__set(ffd->node_revision_cache, &key, *noderev_p,
- pool));
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -3213,20 +3230,22 @@ block_read(void **result,
is_wanted
? -1
: block_start + ffd->block_size,
- pool));
+ pool, iterpool));
break;
case SVN_FS_FS__ITEM_TYPE_NODEREV:
if (ffd->node_revision_cache || is_result)
SVN_ERR(block_read_noderev((node_revision_t **)&item,
fs, revision_file,
- entry, is_result, pool));
+ entry, is_result, pool,
+ iterpool));
break;
case SVN_FS_FS__ITEM_TYPE_CHANGES:
SVN_ERR(block_read_changes((apr_array_header_t **)&item,
fs, revision_file,
- entry, is_result, pool));
+ entry, is_result,
+ pool, iterpool));
break;
default: