The type qualifier is just copy paste relic. We'd of course have to remove const form the signature (and the function body) for this to work. Quickly looking at zend_memrchr's call sites I don't see that it would be a huge issue to modify that or am I missing something?
========== Original ========== From: Levi Morrison <le...@php.net> To: Benjamin Coutu <ben.co...@zeyos.com> Date: Thu, 03 Nov 2016 13:23:23 +0100 Subject: Re: [PHP-DEV] Algorithmic efficiency of zend_memrchr > > > On Thu, Nov 3, 2016 at 5:21 AM, Benjamin Coutu <ben.co...@zeyos.com> wrote: > > Hello everyone, > > > > I think there are a few improvements that we could make to some fundamental > > algorithms. > > I'd like to point out one particular for now, to see if there is any > > interest in these kind of low level code optimizations from the community. > > > > Please consider the following code snippet extracted from > > > > https://github.com/php/php-src/blob/49412756df244d94a217853395d15e96cb60e18f/Zend/zend_operators.h#L193 > > > > static zend_always_inline const void *zend_memrchr(const void *s, int c, > > size_t n) > > { > > const unsigned char *e; > > if (n <= 0) { > > return NULL; > > } > > > > for (e = (const unsigned char *)s + n - 1; e >= (const unsigned char *)s; > > e--) { > > if (*e == (const unsigned char)c) { > > return (const void *)e; > > } > > } > > return NULL; > > } > > > > The issue with this is that on each loop we have to do two comparison > > tests, one against the length boundary and one to check for the actual > > occurrence of the search character. > > > > We can avoid checking the length boundary if we use a sentinel by setting > > the last possible element to the character we are searching for, whereby we > > guarantee that we will find it and no longer need the test inside the loop. > > After the search we reset that character and then recheck the last > > iteration step to see if we have aborted the loop because of reaching the > > end (false positive) or because of an actual positive. > > > > A patch could look like this: > > > > static zend_always_inline const void *zend_memrchr(const void *s, int c, > > size_t n) > > { > > const unsigned char *b; > > const unsigned char *e; > > const unsigned char t; > > > > if (n > 0) { > > /* Initialize boundary pointers */ > > b = (const unsigned char *)s; > > e = b + n - 1; > > > > /* Set sentinel */ > > t = *b; > > *b = (const unsigned char)c; > > > > /* Search */ > > while (*e != (const unsigned char)c) { > > --e; > > } > > > > /* Restore sentinel */ > > *b = t; > > > > /* Recheck */ > > if (e != b || t == (const unsigned char)c) { > > return (const void *)e; > > } > > } > > > > return NULL; > > } > > > > For the above example we could go one step further and test an entire > > longword at a time with alignment on longword boundaries, just like some > > modern C library implementations do. Which begs the question: Is there a > > reason we are not using standard memrchr here? > > > > This kind of approach might be applicable to other string handling > > functions as well. Should I look into this further? > > > > Cheers, > > > > Benjamin Coutu > > > > -- > > > > Bejamin Coutu > > ben.co...@zeyos.com > > > > ZeyOS, Inc. > > http://www.zeyos.com > > > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: http://www.php.net/unsub.php > > An obvious issue with this is that not all strings are writable. The > signature of the function also specifies it is a pointer to a const so > you shouldn't be able to do this anyway. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php