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