Justin, you appear to have resurfaced (to a degree, at least). Did you ever
complete this work?
On 06/18/2012 02:18 AM, Justin Erenkrantz wrote:
> One issue that I've come across in my recent analysis is that ra_serf
> isn't always aggressive in closing directories when doing an update.
> Specifically, when the directory propfind isn't received by the time
> all of the files are processed, ra_serf won't look at the directory
> handle again until everything is complete. (It only evaluates when
> closing the files.) When doing a large checkout (like tags/), this
> can be a bit problematic as we really need to be aggressive in
> reclaiming all of the pools to keep our memory usage down as much as
> possible.
>
> This patch is unfinished...it solves the main issue, but there is some
> corruption in the active_dir_propfinds (which I sort of tried to
> address by using serf's allocator; which isn't a normal paradigm for
> Subversion). When I get back home today, I need to concentrate on my
> pending cross-country move and starting my new position in NYC. So,
> it may be a few weeks before I get any real chance to look at this
> again.
>
> In the meantime, I know that Greg is planning to rewrite the XML
> parsing in update.c to fit the new parsing paradigm that has been
> introduced into other parts of ra_serf as well as getting the Propfind
> depth:1 in. My guess it that after the parsing rewrite and depth 1 is
> complete, this issue may fall by the wayside...or not.
>
> Hence, I'll just throw the current patch on the list for posterity.
> When I come up for air again, I'll try to evaluate if it is still
> needed. FWIW, Instruments on OS X is awesome. -- justin
>
> Index: subversion/libsvn_ra_serf/update.c
> ===================================================================
> --- subversion/libsvn_ra_serf/update.c (revision 1351209)
> +++ subversion/libsvn_ra_serf/update.c (working copy)
> @@ -48,6 +48,8 @@
> #include "ra_serf.h"
> #include "../libsvn_ra/ra_loader.h"
>
> +#include "serf_bucket_util.h"
> +
>
> /*
> * This enum represents the current state of our XML parsing for a REPORT.
> @@ -292,6 +294,7 @@ typedef struct report_fetch_t {
> */
> struct report_context_t {
> apr_pool_t *pool;
> + serf_bucket_alloc_t *allocator;
>
> svn_ra_serf__session_t *sess;
> svn_ra_serf__connection_t *conn;
> @@ -348,7 +351,11 @@ struct report_context_t {
>
> /* completed PROPFIND requests (contains svn_ra_serf__handler_t) */
> svn_ra_serf__list_t *done_propfinds;
> + svn_ra_serf__list_t *done_dir_propfinds;
>
> + /* list of outstanding prop changes (contains report_dir_t) */
> + svn_ra_serf__list_t *active_dir_propfinds;
> +
> /* list of files that only have prop changes (contains report_info_t) */
> svn_ra_serf__list_t *file_propchanges_only;
>
> @@ -654,6 +661,7 @@ close_dir(report_dir_t *dir)
> }
>
> svn_pool_destroy(dir->dir_baton_pool);
> + printf("destroy: %p (%s)\n", dir->pool, dir->name);
> svn_pool_destroy(dir->pool);
>
> return SVN_NO_ERROR;
> @@ -1888,6 +1896,7 @@ end_report(svn_ra_serf__xml_parser_t *parser,
> */
> if (!SVN_IS_VALID_REVNUM(info->dir->base_rev) || info->dir->fetch_props)
> {
> + svn_ra_serf__list_t *list_item;
> /* Unconditionally set fetch_props now. */
> info->dir->fetch_props = TRUE;
>
> @@ -1897,7 +1906,7 @@ end_report(svn_ra_serf__xml_parser_t *parser,
> info->dir->url,
> ctx->target_rev, "0",
> all_props,
> - &ctx->done_propfinds,
> + &ctx->done_dir_propfinds,
> info->dir->pool));
> SVN_ERR_ASSERT(info->dir->propfind_handler);
>
> @@ -1906,6 +1915,11 @@ end_report(svn_ra_serf__xml_parser_t *parser,
>
> ctx->active_propfinds++;
>
> + list_item = serf_bucket_mem_alloc(ctx->allocator,
> sizeof(*list_item));
> + list_item->data = info->dir;
> + list_item->next = ctx->active_dir_propfinds;
> + ctx->active_dir_propfinds = list_item;
> +
> if (ctx->active_fetches + ctx->active_propfinds
> > REQUEST_COUNT_TO_PAUSE)
> ctx->parser_ctx->paused = TRUE;
> @@ -2525,12 +2539,77 @@ finish_report(void *report_baton,
> }
> report->done_propfinds = NULL;
>
> + done_list = report->done_dir_propfinds;
> + while (done_list)
> + {
> + svn_pool_clear(iterpool_inner);
> +
> + report->active_propfinds--;
> +
> + if (report->active_dir_propfinds)
> + {
> + svn_ra_serf__list_t *cur, *prev;
> +
> + cur = report->active_dir_propfinds;
> + prev = NULL;
> +
> + while (cur)
> + {
> + report_dir_t *item = cur->data;
> +
> + if (item->propfind_handler == done_list->data)
> + {
> + break;
> + }
> +
> + prev = cur;
> + cur = cur->next;
> + }
> + if (cur)
> + {
> + report_dir_t *cur_dir = cur->data;
> +
> + while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed
> + && (!cur_dir->fetch_props
> + || cur_dir->propfind_handler->done))
> + {
> + printf("clear: %p : %s\n", cur_dir, cur_dir->name);
> + report_dir_t *parent = cur_dir->parent_dir;
> +
> + SVN_ERR(close_dir(cur_dir));
> + if (parent)
> + {
> + parent->ref_count--;
> + }
> + else
> + {
> + closed_root = TRUE;
> + }
> + cur_dir = parent;
> + }
> +
> + if (!prev)
> + {
> + report->active_dir_propfinds = cur->next;
> + }
> + else
> + {
> + prev->next = cur->next;
> + }
> + serf_bucket_mem_free(report->allocator, cur);
> + }
> + }
> +
> + done_list = done_list->next;
> + }
> + report->done_dir_propfinds = NULL;
> +
> /* prune our fetches list if they are done. */
> done_list = report->done_fetches;
> while (done_list)
> {
> report_fetch_t *done_fetch = done_list->data;
> - report_dir_t *cur_dir;
> + report_dir_t *cur_dir, *t_d;
>
> /* decrease our parent's directory refcount. */
> cur_dir = done_fetch->info->dir;
> @@ -2549,6 +2628,17 @@ finish_report(void *report_baton,
> * we've already completed the propfind
> * then, we know it's time for us to close this directory.
> */
> + t_d = cur_dir;
> + while (t_d) {
> + printf("%p : %s %ld ", t_d, t_d->name, t_d->ref_count);
> + if (t_d->ref_count) {
> + printf("\n");
> + } else {
> + printf("-###- %d %d %p %d\n", t_d->tag_closed,
> t_d->fetch_props, t_d->propfind_handler, t_d->propfind_handler ?
> t_d->propfind_handler->done : -1);
> + }
> + t_d = t_d->parent_dir;
> + }
> +
> while (cur_dir && !cur_dir->ref_count && cur_dir->tag_closed
> && (!cur_dir->fetch_props
> || cur_dir->propfind_handler->done))
> @@ -2674,6 +2764,7 @@ make_update_reporter(svn_ra_session_t *ra_session,
>
> report = apr_pcalloc(result_pool, sizeof(*report));
> report->pool = result_pool;
> + report->allocator = serf_bucket_allocator_create(report->pool, NULL, NULL);
> report->sess = sess;
> report->conn = report->sess->conns[0];
> report->target_rev = revision;
>
--
C. Michael Pilato <cmpilato_at_collab.net>
CollabNet <> www.collab.net <> Enterprise Cloud Development
Received on 2012-08-10 08:21:25 CEST