[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Entries Cache Performance & fast svn_time_from_cstring code

From: Zack Weinberg <zack_at_codesourcery.com>
Date: 2002-11-27 00:55:18 CET

Brandon Ehle <azverkan@yahoo.com> writes:

> I get about a 14% boost with your patch and additional 5% boost with
> using this version of svn_time_from_cstring(). Its not pretty, but
> its pretty fast.

I bet I can squeeze even more cycles out of this. Have fast_strtoul10
store its result into a pointer argument, since that's going to be a
memory write anyway, and return the updated pointer. That'll
facilitate the pointer staying in a register all the time. Also, you
make heavy use of flag variables in the fast path -- better to handle
that with jumps out of the fast path.

Note that the 'register' keyword is ignored by most modern compilers,
so I feel it's best to leave it out.

> With these two changes svn_time_from_cstring() falls completely off
> the profiler and the next bigger hitter is write_entry().

So perhaps further tuning is not helpful, but I'd be curious how the
appended revision stacks up, anyway.

Is significant time spent in apr_psprintf or children thereof? Both
scanf and printf -alikes tend to be slow, and I wouldn't be surprised
if a similar change helped there too.

zw

=============================================

static const char *
fast_strtoul10(const char *s, unsigned long *result)
{
  int c;
  unsigned long val = 0;

  for (;;) {
    c = *s - '0';
    if (c < 0 || c > 9)
      break;
    val = val * 10 + c;
    s++;
  }
  *result = val;
  return s;
}

svn_error_t *
svn_time_from_cstring(apr_time_t *when, const char *data, apr_pool_t *pool)
{
  apr_time_exp_t exploded_time;
  apr_status_t apr_err;
  char wday[4], month[4];
  const char *c = data;

  /* Open-code parsing of the new timestamp format, as this
     is a hot path for reading the entries file. */
  c = fast_strtoul10(c, &exploded_time.tm_year);
  if (*c++ != '-') goto fail;
  c = fast_strtoul10(c, &exploded_time.tm_mon);
  if (*c++ != '-') goto fail;
  c = fast_strtoul10(c, &exploded_time.tm_mday);
  if (*c++ != 'T') goto fail;
  c = fast_strtoul10(c, &exploded_time.tm_hour);
  if (*c++ != ':') goto fail;
  c = fast_strtoul10(c, &exploded_time.tm_min);
  if (*c++ != ':') goto fail;
  c = fast_strtoul10(c, &exploded_time.tm_sec);
  if (*c++ != '.') goto fail;
  c = fast_strtoul10(c, &exploded_time.tm_usec);
  if (*c++ != 'Z') goto fail;

  exploded_time.tm_year -= 1900;
  exploded_time.tm_mon -= 1;
  exploded_time.tm_wday = 0;
  exploded_time.tm_yday = 0;
  exploded_time.tm_isdst = 0;
  exploded_time.tm_gmtoff = 0;

  apr_err = apr_implode_gmt(when, &exploded_time);
  if (apr_err == APR_SUCCESS)
    return SVN_NO_ERROR;

  return svn_error_createf(SVN_ERR_BAD_DATE, apr_err, NULL,
                           "Date conversion failed.");

fail:
  /* Try the compatibility option. This does not need to be fast,
     as this format is no longer generated and the client will convert
     an old-format entries file the first time it reads it. */
  if (sscanf(data, old_timestamp_format,
                   wday,
                   &exploded_time.tm_mday,
                   month,
                   &exploded_time.tm_year,
                   &exploded_time.tm_hour,
                   &exploded_time.tm_min,
                   &exploded_time.tm_sec,
                   &exploded_time.tm_usec,
                   &exploded_time.tm_yday,
                   &exploded_time.tm_isdst,
                   &exploded_time.tm_gmtoff) == 11)
    {
      exploded_time.tm_year -= 1900;
      exploded_time.tm_yday -= 1;
      /* Using hard coded limits for the arrays - they are going away
         soon in any case. */
      exploded_time.tm_wday = find_matching_string(wday, 7, apr_day_snames);
      exploded_time.tm_mon = find_matching_string(month, 12, apr_month_snames);

      apr_err = apr_implode_gmt(when, &exploded_time);
      if (apr_error == APR_SUCCESS)
        return SVN_NO_ERROR;

      return svn_error_createf(SVN_ERR_BAD_DATE, apr_err, NULL,
                               "Date conversion failed.");
    }

  /* Timestamp is something we do not recognize. */
  return svn_error_createf(SVN_ERR_BAD_DATE, 0, NULL,
                           "Date parsing failed.");
}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Nov 27 00:56:01 2002

This is an archived mail posted to the Subversion Dev mailing list.