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 <cmpil...@collab.net>
CollabNet   <>   www.collab.net   <>   Enterprise Cloud Development

Reply via email to