Re: svn commit: r1715876 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
On 11/23/2015 05:46 PM, yla...@apache.org wrote: > Author: ylavic > Date: Mon Nov 23 16:46:01 2015 > New Revision: 1715876 > > URL: http://svn.apache.org/viewvc?rev=1715876=rev > Log: > Use new ap_casecmpstr[n]() functions where appropriate (not exhaustive). > > Modified: > httpd/httpd/trunk/modules/cache/cache_util.c > httpd/httpd/trunk/modules/filters/mod_deflate.c > httpd/httpd/trunk/modules/filters/mod_include.c > httpd/httpd/trunk/modules/filters/mod_proxy_html.c > httpd/httpd/trunk/modules/generators/mod_autoindex.c > httpd/httpd/trunk/modules/generators/mod_cgi.c > httpd/httpd/trunk/modules/generators/mod_cgid.c > httpd/httpd/trunk/modules/http/byterange_filter.c > httpd/httpd/trunk/modules/http/http_filters.c > httpd/httpd/trunk/modules/http2/h2_from_h1.c > httpd/httpd/trunk/modules/loggers/mod_log_config.c > httpd/httpd/trunk/modules/mappers/mod_rewrite.c > httpd/httpd/trunk/modules/metadata/mod_cern_meta.c > httpd/httpd/trunk/modules/metadata/mod_headers.c > httpd/httpd/trunk/modules/proxy/ajp_header.c > httpd/httpd/trunk/modules/proxy/mod_proxy.c > httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c > httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c > httpd/httpd/trunk/modules/proxy/mod_proxy_fcgi.c > httpd/httpd/trunk/modules/proxy/mod_proxy_fdpass.c > httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c > httpd/httpd/trunk/modules/proxy/mod_proxy_http.c > httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c > httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c > httpd/httpd/trunk/modules/proxy/mod_serf.c > httpd/httpd/trunk/modules/proxy/proxy_util.c > httpd/httpd/trunk/modules/slotmem/mod_slotmem_shm.c > httpd/httpd/trunk/modules/test/mod_policy.c > httpd/httpd/trunk/server/mpm_unix.c > httpd/httpd/trunk/server/protocol.c > httpd/httpd/trunk/server/util.c > httpd/httpd/trunk/server/util_expr_eval.c > httpd/httpd/trunk/server/util_script.c > > Modified: httpd/httpd/trunk/modules/cache/cache_util.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/cache_util.c?rev=1715876=1715875=1715876=diff > == > --- httpd/httpd/trunk/modules/cache/cache_util.c (original) > +++ httpd/httpd/trunk/modules/cache/cache_util.c Mon Nov 23 16:46:01 2015 > @@ -1066,59 +1045,46 @@ int ap_cache_control(request_rec *r, cac > cc->max_stale = 1; > cc->max_stale_value = -1; > } > -break; > } > -else if (!strncasecmp(token, "min-fresh", 9)) { > +else if (!ap_casecmpstrn(token, "min-fresh", 9)) { > if (token[9] == '=') { > cc->min_fresh = 1; > cc->min_fresh_value = apr_atoi64(token + 10); > } > -break; > -} > -else if (!strcasecmp(token, "must-revalidate")) { > -cc->must_revalidate = 1; > } > break; > } > case 'o': > case 'O': { > -if (!strcasecmp(token, "only-if-cached")) { > +if (!ap_casecmpstr(token, "only-if-cached")) { > cc->only_if_cached = 1; > } > break; > } > -case 'p': > -case 'P': { > -/* handle most common quickest cases... */ > -if (!strcmp(token, "private")) { > -cc->private = 1; > -} > -/* ...then try slowest cases */ > -else if (!strcasecmp(token, "public")) { > +case 'p': { Why removing the uppercase 'P' case here? Regards Rüdiger
Re: svn commit: r1715876 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
Hi, 1 typo below. Moreover, this kind of patch is a good candidate for backport as it introduces many small differences between 2.4 and trunk. Without a backport, backporting future patches may become a nightmare. I would find useful to split it into several pieces. The first one should apply cleanly to 2.4.x to ease backport. Other parts should be splitted in "as many piece as necessary" for potential future backport. CJ Le 23/11/2015 17:46, yla...@apache.org a écrit : Author: ylavic Date: Mon Nov 23 16:46:01 2015 New Revision: 1715876 URL: http://svn.apache.org/viewvc?rev=1715876=rev Log: Use new ap_casecmpstr[n]() functions where appropriate (not exhaustive). Modified: Modified: httpd/httpd/trunk/modules/cache/cache_util.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/cache_util.c?rev=1715876=1715875=1715876=diff == --- httpd/httpd/trunk/modules/cache/cache_util.c (original) +++ httpd/httpd/trunk/modules/cache/cache_util.c Mon Nov 23 16:46:01 2015 [...] @@ -1066,59 +1045,46 @@ int ap_cache_control(request_rec *r, cac cc->max_stale = 1; cc->max_stale_value = -1; } -break; } -else if (!strncasecmp(token, "min-fresh", 9)) { +else if (!ap_casecmpstrn(token, "min-fresh", 9)) { if (token[9] == '=') { cc->min_fresh = 1; cc->min_fresh_value = apr_atoi64(token + 10); } -break; Thanks for that. I was about to commit the same kind of patch (remove useless break). -} -else if (!strcasecmp(token, "must-revalidate")) { -cc->must_revalidate = 1; } break; } case 'o': case 'O': { -if (!strcasecmp(token, "only-if-cached")) { +if (!ap_casecmpstr(token, "only-if-cached")) { cc->only_if_cached = 1; } break; } -case 'p': -case 'P': { -/* handle most common quickest cases... */ -if (!strcmp(token, "private")) { -cc->private = 1; -} -/* ...then try slowest cases */ -else if (!strcasecmp(token, "public")) { +case 'p': { case 'P' removed? Best regards, CJ
Re: svn commit: r1715876 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
On Mon, Nov 23, 2015 at 8:37 PM, Ruediger Pluemwrote: > > On 11/23/2015 05:46 PM, yla...@apache.org wrote: >> >> -case 'p': >> -case 'P': { >> -/* handle most common quickest cases... */ >> -if (!strcmp(token, "private")) { >> -cc->private = 1; >> -} >> -/* ...then try slowest cases */ >> -else if (!strcasecmp(token, "public")) { >> +case 'p': { > > Why removing the uppercase 'P' case here? Not intentional, fixed in r1715938. Thanks for noticing. Regards, Yann.
Re: svn commit: r1715876 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
On Mon, Nov 23, 2015 at 9:00 PM, Marion & Christophe JAILLETwrote: > Hi, > > 1 typo below. Fixed in r1715938, thanks. > > Moreover, this kind of patch is a good candidate for backport as it > introduces many small differences between 2.4 and trunk. > Without a backport, backporting future patches may become a nightmare. Agreed. > > I would find useful to split it into several pieces. > The first one should apply cleanly to 2.4.x to ease backport. > Other parts should be splitted in "as many piece as necessary" for potential > future backport. I'll try to merge with svn, and resolve conflicts... Regards, Yann.
Re: strncasecmp
Hi Jim, Do you have done some benchmark and have results to share? I tried to do some but the benefit of the optimized version is not that clear, at least on my system: gcc 5.2.1 Linux linux 4.2.0-18-generic #22-Ubuntu SMP Fri Nov 6 18:25:50 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux I've tried to trick gcc in order to avoid some optimization. (gcc does its best to remove/inline/remove from loop known standard C functions) I've check asm output to be more confident on the code generated by gcc. Based on my own results only, and without any becnhmark, I would -1 a backport. For small strings (below identical char), your implementation looks faster, but above 4 identical chars it looks slower I can provide my test program if interested. best regards, CJ Le 20/11/2015 19:53, Jim Jagielski a écrit : Implemented in r1715401 If people want to nit-pick about naming and wish to rename it to something else, be my guest. On Nov 20, 2015, at 1:03 PM, Yann Ylavicwrote: +1 On Fri, Nov 20, 2015 at 6:17 PM, Jim Jagielski wrote: We use str[n]casecmp quite a bit. The rub is that some platforms use a sensible implementation (such as OSX) which uses a upper-lowercase map and is v. fast, and others use a brain-dead version which does an actual tolower() of each char in the string as it tests. We actually try to handle this in many cases by doing a switch/case test on the 1st char to fast path the strncasecmp, resulting in ugly code. This is crazy. I propose a ap_strncasecmp/ap_strcasecmp which we should use. Ideally, it would be in apr but no need to wait for that to happen :) Unless people have heartburn about this, I will add next week.
Re: strncasecmp
Hi Christophe, On Mon, Nov 23, 2015 at 9:12 PM, Christophe JAILLETwrote: > > I tried to do some but the benefit of the optimized version is not that > clear, at least on my system: >gcc 5.2.1 >Linux linux 4.2.0-18-generic #22-Ubuntu SMP Fri Nov 6 18:25:50 UTC 2015 > x86_64 x86_64 x86_64 GNU/Linux Unfortunately, gcc 5.2.1 (i.e. latest compilers' versions) are not widely used... Did you try a code like ap_proxy_port_of_scheme() with values which are unknown schemes? Or even worse cases, with similarly chained strcasecmp() looking for eg. "httpx" in something like {"httpa", "httpb", "httpc", ..., "httpw"}? Regards, Yann.
Re: svn commit: r1715554 - /httpd/httpd/trunk/server/util.c
++1 > On Nov 22, 2015, at 10:33 AM, William A Rowe Jrwrote: > > On Sat, Nov 21, 2015 at 5:10 PM, Eric Covener wrote: > On Sat, Nov 21, 2015 at 5:47 PM, William A Rowe Jr > wrote: > > I suggest this is wrong, and that the appropriate table should be built. > > > > EBCDIC platforms do have i18n (typicially single-byte) lower/upper > > equivalences, and the underlying implementation should not be trusted for > > straight ASCII token case insensitive comparisons. > > I don't see it why it shouldn't be trusted, but I've reverted for now, > > I'll revisit when this settles down / the function is used somewhere. > > Have a look at r1715632 and let me know what you think. > > I see a lot of ill-defined or otherwise vague string functions, many of them > are somewhat duplicate in nature, several of them questionable (unbounded > recursion, really?) It is probably time to move these all out to > util_strings.c > and really evaluate which are appropriate to use in which contexts, while > others should probably be evicted from trunk. ap_strcmp_match looks like > the first worst offender (apr_fnmatch is already a much safer implementation.) > > >
Re: svn commit: r1715789 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
> On Nov 23, 2015, at 7:33 AM, yla...@apache.org wrote: > > Author: ylavic > Date: Mon Nov 23 12:33:09 2015 > New Revision: 1715789 > > URL: http://svn.apache.org/viewvc?rev=1715789=rev > Log: > Use new ap_casecmpstr[n]() functions where appropriate (not exhaustive). > > > Modified: httpd/httpd/trunk/modules/cache/cache_util.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/cache_util.c?rev=1715789=1715788=1715789=diff > == > --- httpd/httpd/trunk/modules/cache/cache_util.c (original) > +++ httpd/httpd/trunk/modules/cache/cache_util.c Mon Nov 23 12:33:09 2015 > @@ -594,7 +594,12 @@ int cache_check_freshness(cache_handle_t > } > > if ((agestr = apr_table_get(h->resp_hdrs, "Age"))) { > -age_c = apr_atoi64(agestr); > +char *endp; > +apr_off_t offt; > +if (!apr_strtoff(, agestr, , 10) > +&& endp > agestr && !*endp) { > +age_c = offt; > +} > } > > /* calculate age of object */ > That's cheating :)
Re: strncasecmp
I modified your test program a bit (to measure time from it, see attached), tried with -O{2,3,s}, and except -Os I always have better results with the "optimized" version, eg: $ ./a-O3.out 0 15000 xcxcxcxcxcxcxcxcxcxcwwaa xcxcxcxcxcxcxcxcxcxcwwaa 0 (nb=15000, len=0) time = 8.424984 : res = 0 $ ./a-O3.out 1 15000 xcxcxcxcxcxcxcxcxcxcwwaa xcxcxcxcxcxcxcxcxcxcwwaa 0 Optimized (nb=15000, len=0) time = 8.212137 : res = 0 Possibly gcc (v4.4.5 here) is clever enough to optimize/inline/cheat when given standard (no custom) code, since I had similar results than yours with the original test.c... How does this one work with gcc-5.2? On Mon, Nov 23, 2015 at 10:07 PM, Marion & Christophe JAILLETwrote: > I just made a small application which takes as command line parameters the > number of iteration to run, which version of the algorithm to use, the 2 > strings to compare and the length to compare (or 0 for the non 'n' versions) > > > Compiled using > gcc -O3 test.c > > Tested using > linux:~/Code_Source$ time ./a.out 1 1 > xcxcxcxcxcxcxcxcxcxcwwaa > xcxcxcxcxcxcxcxcxcxcwwaa 0 > Optimized (nb=1, len=0) > res = 0 > > real0m4.193s > user0m4.192s > sys0m0.000s > > > > linux:~/Code_Source$ time ./a.out 0 1 > xcxcxcxcxcxcxcxcxcxcwwaa > xcxcxcxcxcxcxcxcxcxcwwaa 0 > (nb=1, len=0) > res = 0 > > real0m1.708s > user0m1.704s > sys0m0.000s > > > > > See atatchement. > > CJ > > > > Le 23/11/2015 21:33, Yann Ylavic a écrit : >> >> Hi Christophe, >> >> On Mon, Nov 23, 2015 at 9:12 PM, Christophe JAILLET >> wrote: >>> >>> I tried to do some but the benefit of the optimized version is not that >>> clear, at least on my system: >>> gcc 5.2.1 >>> Linux linux 4.2.0-18-generic #22-Ubuntu SMP Fri Nov 6 18:25:50 UTC >>> 2015 >>> x86_64 x86_64 x86_64 GNU/Linux >> >> Unfortunately, gcc 5.2.1 (i.e. latest compilers' versions) are not >> widely used... >> >> Did you try a code like ap_proxy_port_of_scheme() with values which >> are unknown schemes? >> Or even worse cases, with similarly chained strcasecmp() looking for >> eg. "httpx" in something like {"httpa", "httpb", "httpc", ..., >> "httpw"}? >> >> Regards, >> Yann. >> >
Re: strncasecmp
Please note that the changes in ap_str[n]casecmp(), ie: ++ps1; ++ps2; was a first try/change which (obviously) did nothing. You may ignore it. On Mon, Nov 23, 2015 at 11:43 PM, Yann Ylavicwrote: > with attachment... > > On Mon, Nov 23, 2015 at 11:42 PM, Yann Ylavic wrote: >> I modified your test program a bit (to measure time from it, see >> attached), tried with -O{2,3,s}, and except -Os I always have better >> results with the "optimized" version, eg: >> >> $ ./a-O3.out 0 15000 xcxcxcxcxcxcxcxcxcxcwwaa >> xcxcxcxcxcxcxcxcxcxcwwaa 0 >> (nb=15000, len=0) >> time = 8.424984 : res = 0 >> >> $ ./a-O3.out 1 15000 xcxcxcxcxcxcxcxcxcxcwwaa >> xcxcxcxcxcxcxcxcxcxcwwaa 0 >> Optimized (nb=15000, len=0) >> time = 8.212137 : res = 0 >> >> Possibly gcc (v4.4.5 here) is clever enough to optimize/inline/cheat >> when given standard (no custom) code, since I had similar results than >> yours with the original test.c... >> >> How does this one work with gcc-5.2? >> >> On Mon, Nov 23, 2015 at 10:07 PM, Marion & Christophe JAILLET >> wrote: >>> I just made a small application which takes as command line parameters the >>> number of iteration to run, which version of the algorithm to use, the 2 >>> strings to compare and the length to compare (or 0 for the non 'n' versions) >>> >>> >>> Compiled using >>> gcc -O3 test.c >>> >>> Tested using >>> linux:~/Code_Source$ time ./a.out 1 1 >>> xcxcxcxcxcxcxcxcxcxcwwaa >>> xcxcxcxcxcxcxcxcxcxcwwaa 0 >>> Optimized (nb=1, len=0) >>> res = 0 >>> >>> real0m4.193s >>> user0m4.192s >>> sys0m0.000s >>> >>> >>> >>> linux:~/Code_Source$ time ./a.out 0 1 >>> xcxcxcxcxcxcxcxcxcxcwwaa >>> xcxcxcxcxcxcxcxcxcxcwwaa 0 >>> (nb=1, len=0) >>> res = 0 >>> >>> real0m1.708s >>> user0m1.704s >>> sys0m0.000s >>> >>> >>> >>> >>> See atatchement. >>> >>> CJ >>> >>> >>> >>> Le 23/11/2015 21:33, Yann Ylavic a écrit : Hi Christophe, On Mon, Nov 23, 2015 at 9:12 PM, Christophe JAILLET wrote: > > I tried to do some but the benefit of the optimized version is not that > clear, at least on my system: > gcc 5.2.1 > Linux linux 4.2.0-18-generic #22-Ubuntu SMP Fri Nov 6 18:25:50 UTC > 2015 > x86_64 x86_64 x86_64 GNU/Linux Unfortunately, gcc 5.2.1 (i.e. latest compilers' versions) are not widely used... Did you try a code like ap_proxy_port_of_scheme() with values which are unknown schemes? Or even worse cases, with similarly chained strcasecmp() looking for eg. "httpx" in something like {"httpa", "httpb", "httpc", ..., "httpw"}? Regards, Yann. >>>
Re: strncasecmp
with attachment... On Mon, Nov 23, 2015 at 11:42 PM, Yann Ylavicwrote: > I modified your test program a bit (to measure time from it, see > attached), tried with -O{2,3,s}, and except -Os I always have better > results with the "optimized" version, eg: > > $ ./a-O3.out 0 15000 xcxcxcxcxcxcxcxcxcxcwwaa > xcxcxcxcxcxcxcxcxcxcwwaa 0 > (nb=15000, len=0) > time = 8.424984 : res = 0 > > $ ./a-O3.out 1 15000 xcxcxcxcxcxcxcxcxcxcwwaa > xcxcxcxcxcxcxcxcxcxcwwaa 0 > Optimized (nb=15000, len=0) > time = 8.212137 : res = 0 > > Possibly gcc (v4.4.5 here) is clever enough to optimize/inline/cheat > when given standard (no custom) code, since I had similar results than > yours with the original test.c... > > How does this one work with gcc-5.2? > > On Mon, Nov 23, 2015 at 10:07 PM, Marion & Christophe JAILLET > wrote: >> I just made a small application which takes as command line parameters the >> number of iteration to run, which version of the algorithm to use, the 2 >> strings to compare and the length to compare (or 0 for the non 'n' versions) >> >> >> Compiled using >> gcc -O3 test.c >> >> Tested using >> linux:~/Code_Source$ time ./a.out 1 1 >> xcxcxcxcxcxcxcxcxcxcwwaa >> xcxcxcxcxcxcxcxcxcxcwwaa 0 >> Optimized (nb=1, len=0) >> res = 0 >> >> real0m4.193s >> user0m4.192s >> sys0m0.000s >> >> >> >> linux:~/Code_Source$ time ./a.out 0 1 >> xcxcxcxcxcxcxcxcxcxcwwaa >> xcxcxcxcxcxcxcxcxcxcwwaa 0 >> (nb=1, len=0) >> res = 0 >> >> real0m1.708s >> user0m1.704s >> sys0m0.000s >> >> >> >> >> See atatchement. >> >> CJ >> >> >> >> Le 23/11/2015 21:33, Yann Ylavic a écrit : >>> >>> Hi Christophe, >>> >>> On Mon, Nov 23, 2015 at 9:12 PM, Christophe JAILLET >>> wrote: I tried to do some but the benefit of the optimized version is not that clear, at least on my system: gcc 5.2.1 Linux linux 4.2.0-18-generic #22-Ubuntu SMP Fri Nov 6 18:25:50 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux >>> >>> Unfortunately, gcc 5.2.1 (i.e. latest compilers' versions) are not >>> widely used... >>> >>> Did you try a code like ap_proxy_port_of_scheme() with values which >>> are unknown schemes? >>> Or even worse cases, with similarly chained strcasecmp() looking for >>> eg. "httpx" in something like {"httpa", "httpb", "httpc", ..., >>> "httpw"}? >>> >>> Regards, >>> Yann. >>> >> #include #include #include #include /* * Provide our own known-fast implementation of str[n]casecmp() * NOTE: ASCII only! */ static const unsigned char ucharmap[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; int ap_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (ucharmap[*ps1] == ucharmap[*ps2]) { if (*ps1 == '\0') { return (0); } ++ps1; ++ps2; } return (ucharmap[*ps1] - ucharmap[*--ps2]); } int ap_strncasecmp(const char *s1, const char *s2, int n) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2;
Re: svn commit: r1715876 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
On Nov 23, 2015 14:12, "Yann Ylavic"wrote: > > On Mon, Nov 23, 2015 at 9:00 PM, Marion & Christophe JAILLET > wrote: > > > > Moreover, this kind of patch is a good candidate for backport as it > > introduces many small differences between 2.4 and trunk. > > Without a backport, backporting future patches may become a nightmare. > > Agreed. > > > > > I would find useful to split it into several pieces. > > The first one should apply cleanly to 2.4.x to ease backport. > > Other parts should be splitted in "as many piece as necessary" for potential > > future backport. > > I'll try to merge with svn, and resolve conflicts... Moreover, I didn't have a chance to review the patch, but all of the instances that 1. map to an RFC protocol string comparison and 2. occur in 2.4 code base *should* be coalesced into one patch. I'm +1 for every such change. The rest of the RFC token comparisons can be added individually for later merging with their associated bug or enhancement backports. I'm strongly -1 for using this function to 'optimize' what is otherwise a non-spec string comparison. There is no excuse for us to defeat good implementations of strcasecmp for the benefit of platforms with shoddy implementations. Jim proposed this as an optimization but I reject that, and wholeheartedly support his suggested use of a predictable ASCII-only folding comparison when following any spec that defines token strings in terms of ASCII alpha chars. We aren't writing a clib but we do have to be mindful of i18n side-effects of the clib we are running within.
Re: strncasecmp
On 23.11.2015 23:14, William A Rowe Jr wrote: > L1 cache and other direct effects of cpu internal optimization. Just what I was thinking. Attached is the same program with one more pair of functions added (and an easy way to add more "candidates" to the main-driver). I changed the FOR-loop define to obtain repeatable results: # Test 1 -- equal strings: foreach m ( 0 1 2 ) foreach? ./strncasecmp $m 1 a A 7 foreach? end string.h (nb=1, len=7) time = 6.975845 : res = 0 optimized (nb=1, len=7) time = 1.492197 : res = 0 'A' - 'a' (nb=1, len=7) time = 1.787807 : res = 0 # Test 2 -- immediately-different strings foreach m ( 0 1 2 ) foreach? ./strncasecmp $m 1 a x 7 foreach? end string.h (nb=1, len=7) time = 2.527727 : res = -23 optimized (nb=1, len=7) time = 0.406867 : res = -23 'A' - 'a' (nb=1, len=7) time = 0.440320 : res = -23 # Test 3 -- strings different at the very end foreach m ( 0 1 2 ) foreach? ./strncasecmp $m 1 a x 0 foreach? end string.h (nb=1, len=0) time = 9.629660 : res = -23 optimized (nb=1, len=0) time = 1.387208 : res = -23 'A' - 'a' (nb=1, len=0) time = 1.754683 : res = -23 The new pair (method 2) does not use the static table, which is likely to benefit from CPU-cache unfairly in repetitive benchmarks. It is slower than the table-using method 1 functions. But the two pairs might be comparable -- or even faster -- in real life. -mi #include #include #include #define gettimeofday(X) gettimeofday(X, NULL) #include #include #include #include #include #include /* * Provide our own known-fast implementation of str[n]casecmp() * NOTE: ASCII only! */ static const unsigned char ucharmap[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; int ap_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (*ps1 == *ps2 || ucharmap[*ps1] == ucharmap[*ps2]) { if (*ps1 == '\0') { return (0); } ++ps1; ++ps2; } return (ucharmap[*ps1] - ucharmap[*ps2]); } int ap_strncasecmp(const char *s1, const char *s2, size_t n) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (n--) { if (*ps1 == *ps2 || ucharmap[*ps1] != ucharmap[*ps2]) { return (ucharmap[*ps1] - ucharmap[*ps2]); } if (*ps1 == '\0') { break; } ++ps1; ++ps2; } return (0); } int mi_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; for (;;) { int diff = *ps1 - *ps2; switch (diff) { case 0: break; case 'A' - 'a': if (*ps1 <= 'Z' && *ps1 >= 'A') break; return 1; case 'a' - 'A': if (*ps2 <= 'Z' && *ps2 >= 'A')
Re: strncasecmp
On Nov 23, 2015 21:12, "Mikhail T."wrote: > > On 23.11.2015 19:43, Yann Ylavic wrote: >> >> No measured difference in my tests, I guess it depends on likelyhood to fail/succeed early in the string or not. > > ? I don't see, where it wins anything -- but I do see, where it loses a little... > >> That's expected (or at least no cared about in this test case). We simply want res to not be optimized out, so print it before leaving, without any particular relevance for its value (string.h and optimized versions should return the same res with the same args, ascii strings only, though). > > Yes, we do want the value printed -- such as to catch the kind of errors I reported earlier. But my question was, why does the value change depending on the number of iterations? L1 cache and other direct effects of cpu internal optimization. You would be better off introducing a non-optimizable operation consuming most cpu registers and the L1 cache between iterations if you want to predict the non-repeditive invocation of this function in different contexts throughout the processing phases.
[Dev] GSoC Intro and Contribution to Apache
Hi, I'm Vithulan, Undergraduate of Computer Science and Engineering in University of Moratuwa, Sri lanka. I have quite experience in Java, JavaScript, Android and Open Source, Currently doing my internship in a open source middle-ware company. I'm a potential GSoC candidate, and would love to help your guidance on how should I proceed? Thanks. Regards, Vithulan MV. -- M.V.Vithulan
Re: strncasecmp
On 23.11.2015 19:05, Yann Ylavic wrote: > Here is the correct (new) test, along with the diff wrt the original > (Christophe's) test.c. BTW, if the program measures its own time, should it not use getrusage() instead of gettimeofday()? -mi
Re: strncasecmp
On Tue, Nov 24, 2015 at 1:07 AM, Mikhail T.wrote: > > BTW, if the program measures its own time, should it not use getrusage() > instead of gettimeofday()? Well, it measures the time spent in the relevant code, with a monotonic clock, that should be fair enough. We don't care about the whole process time and other counters. Regards, Yann.
Re: strncasecmp
On Mon, Nov 23, 2015 at 11:42 PM, Yann Ylavicwrote: > except -Os I always have better > results with the "optimized" version To reach better performances with -Os, we could possibly use: int ap_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; for (;;) { const unsigned int c1 = ucharmap[*ps1++], c2 = ucharmap[*ps2++]; if (c1 != c2) { return c1 - c2; } if (c1 == '\0') { break; } } return (0); } int ap_strncasecmp(const char *s1, const char *s2, int n) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (n--) { const unsigned int c1 = ucharmap[*ps1++], c2 = ucharmap[*ps2++]; if (c1 != c2) { return c1 - c2; } if (c1 == '\0') { break; } } return (0); } This implementation with -Os is ~13% slower than str[n]casemp(), whereas the original ap_str[n]casemp() is ~30% slower. Don't know if it happens/makes sense to compile httpd with -Os... At least for APR, I think we could take that into consideration.
Re: strncasecmp
On 23.11.2015 17:43, Yann Ylavic wrote: > with attachment... There is a mistake somewhere in the optimized version: ./o 1 1 aa1a 0 Optimized (nb=1, len=0) time = 0.611311 : res = 0 The result should not be zero. Indeed, the string.h version is correct: ./o 0 1 aa1a 0 (nb=1, len=0) time = 4.189366 : res = 48 Yours, -mi
Re: strncasecmp
On 23.11.2015 19:05, Yann Ylavic wrote: > while (ucharmap[*ps1] == ucharmap[*ps2++]) { > if (*ps1++ == '\0') { > return (0); > } > } > return (ucharmap[*ps1] - ucharmap[*--ps2]); Is there really a gain in inc- and decrementing this way? Would not it be easier to read with the explicit increments -- and, incidentally, no decrements at all? while (ucharmap[*ps1] == ucharmap[*ps2]) { if (*ps1 == '\0') { return (0); } ++ps1; ++ps2; } return (ucharmap[*ps1] - ucharmap[*ps2]); > We don't care about the whole process time and other counters. That's certainly true. But, then, why bother with building time-counter into the test at all -- instead of simply relying on time(1)? But something is still not right -- the result (for either of the methods) can depend on the number of iterations (!!): ./strncasecmp 1 27 aCaa Ac 2 Optimized (nb=27, len=2) time = 0.01 : res = 32 ./strncasecmp 1 26 aCaa Ac 2 Optimized (nb=26, len=2) time = 0.01 : res = 0 ./strncasecmp 0 27 aCaa Ac 2 (nb=27, len=2) time = 0.03 : res = 32 ./strncasecmp 0 26 aCaa Ac 2 (nb=26, len=2) time = 0.03 : res = 0 Using clang on FreeBSD/amd64 here. Yours, -mi
Re: strncasecmp
FWIW, a new version using clock_gettime() instead of gettimeofday(). Same/Comparable results for optimized vs string.h's (the former wins but with -Os). On Tue, Nov 24, 2015 at 1:43 AM, Yann Ylavicwrote: > On Tue, Nov 24, 2015 at 1:24 AM, Mikhail T. wrote: >> >> Is there really a gain in inc- and decrementing this way? Would not it be >> easier to read with the explicit increments -- and, incidentally, no >> decrements at all? > > No measured difference in my tests, I guess it depends on likelyhood > to fail/succeed early in the string or not. > >>> >>> We don't care about the whole process time and other counters. >> >> That's certainly true. But, then, why bother with building time-counter into >> the test at all -- instead of simply relying on time(1)? > > That's the purpose of newtest.c (vs Christophe's test.c): try both... > >> >> But something is still not right -- the result (for either of the methods) >> can depend on the number of iterations (!!): > > That's expected (or at least no cared about in this test case). > We simply want res to not be optimized out, so print it before > leaving, without any particular relevance for its value (string.h and > optimized versions should return the same res with the same args, > ascii strings only, though). #include #include #include #include #include #include /* * Provide our own known-fast implementation of str[n]casecmp() * NOTE: ASCII only! */ static const unsigned char ucharmap[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; int ap_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (ucharmap[*ps1] == ucharmap[*ps2++]) { if (*ps1++ == '\0') { return (0); } } return (ucharmap[*ps1] - ucharmap[*--ps2]); } int ap_strncasecmp(const char *s1, const char *s2, int n) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (n--) { if (ucharmap[*ps1] != ucharmap[*ps2++]) { return (ucharmap[*ps1] - ucharmap[*--ps2]); } if (*ps1++ == '\0') { break; } } return (0); } #define PROG argv[0] #define METHOD argv[1] #define NB argv[2] #define S1 argv[3] #define S2 argv[4] #define LEN argv[5] /* The ++ are here to try to prevent some optimization done by gcc */ #define FOR for (i=0; i S1 S2 \n", PROG); return 0; } len = atoi(LEN); nb = atoi(NB); if (*METHOD == '0') { printf(" (nb=%d, len=%d)\n", nb, len); clock_gettime(CLOCK_MONOTONIC, ); if (len == 0) { FOR { /* really use the result of the function */ res |= strcasecmp(S1, S2); } } else { FOR { res |= strncasecmp(S1, S2, len); } } clock_gettime(CLOCK_MONOTONIC, ); } else { printf("Optimized (nb=%d, len=%d)\n", nb, len);
Re: strncasecmp
On Tue, Nov 24, 2015 at 12:46 AM, Mikhail T.wrote: > On 23.11.2015 17:43, Yann Ylavic wrote: > > with attachment... > > There is a mistake somewhere in the optimized version: My bad, I somehow corrupted the original ap_str[n]casecmp() functions. Here is the correct (new) test, along with the diff wrt the original (Christophe's) test.c. Thanks, Yann. --- test.c 2015-11-24 01:01:29.039339318 +0100 +++ newtest.c 2015-11-24 00:57:13.720817895 +0100 @@ -1,8 +1,10 @@ #include +#include #include #include #include +#include /* * Provide our own known-fast implementation of str[n]casecmp() @@ -83,6 +85,8 @@ int ap_strncasecmp(const char *s1, const int main(int argc, char *argv[]) { +int64_t diff; +struct timeval tvs, tve; int i, len, nb; int res = 0; @@ -96,6 +100,7 @@ int main(int argc, char *argv[]) if (*METHOD == '0') { printf(" (nb=%d, len=%d)\n", nb, len); +gettimeofday(, NULL); if (len == 0) { FOR { /* really use the result of the function */ @@ -107,9 +112,11 @@ int main(int argc, char *argv[]) res |= strncasecmp(S1, S2, len); } } +gettimeofday(, NULL); } else { printf("Optimized (nb=%d, len=%d)\n", nb, len); +gettimeofday(, NULL); if (len == 0) { FOR { res |= ap_strcasecmp(S1, S2); @@ -120,9 +127,16 @@ int main(int argc, char *argv[]) res |= ap_strncasecmp(S1, S2, len); } } +gettimeofday(, NULL); } - + +diff = (int64_t)tve.tv_sec * 100L + tve.tv_usec; +diff -= (int64_t)tvs.tv_sec * 100L + tvs.tv_usec; + /* really use the result of the function */ -printf("res = %d\n", res); +printf("time = %lld.%.6lld : res = %d\n", +(long long)diff / 100L, +(long long)diff % 100L, +res); return 0; } #include #include #include #include #include #include /* * Provide our own known-fast implementation of str[n]casecmp() * NOTE: ASCII only! */ static const unsigned char ucharmap[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; int ap_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (ucharmap[*ps1] == ucharmap[*ps2++]) { if (*ps1++ == '\0') { return (0); } } return (ucharmap[*ps1] - ucharmap[*--ps2]); } int ap_strncasecmp(const char *s1, const char *s2, int n) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (n--) { if (ucharmap[*ps1] != ucharmap[*ps2++]) { return (ucharmap[*ps1] - ucharmap[*--ps2]); } if (*ps1++ == '\0') { break; } } return (0); } #define PROG argv[0] #define METHOD argv[1] #define NB argv[2] #define S1 argv[3] #define S2 argv[4] #define LEN argv[5] /* The ++ are here to try to prevent some optimization done by gcc */ #define FOR for (i=0; i
Re: strncasecmp
On Tue, Nov 24, 2015 at 1:24 AM, Mikhail T.wrote: > > Is there really a gain in inc- and decrementing this way? Would not it be > easier to read with the explicit increments -- and, incidentally, no > decrements at all? No measured difference in my tests, I guess it depends on likelyhood to fail/succeed early in the string or not. >> >> We don't care about the whole process time and other counters. > > That's certainly true. But, then, why bother with building time-counter into > the test at all -- instead of simply relying on time(1)? That's the purpose of newtest.c (vs Christophe's test.c): try both... > > But something is still not right -- the result (for either of the methods) > can depend on the number of iterations (!!): That's expected (or at least no cared about in this test case). We simply want res to not be optimized out, so print it before leaving, without any particular relevance for its value (string.h and optimized versions should return the same res with the same args, ascii strings only, though).
Re: strncasecmp
On 23.11.2015 19:43, Yann Ylavic wrote: > No measured difference in my tests, I guess it depends on likelyhood to > fail/succeed early in the string or not. ? I don't see, where it wins anything -- but I do see, where it loses a little... > That's expected (or at least no cared about in this test case). We > simply want res to not be optimized out, so print it before leaving, > without any particular relevance for its value (string.h and optimized > versions should return the same res with the same args, ascii strings > only, though). Yes, we do want the value printed -- such as to catch the kind of errors I reported earlier. But my question was, why does the value change depending on the number of iterations? -mi
Re: svn commit: r1715789 - in /httpd/httpd/trunk: modules/cache/ modules/filters/ modules/generators/ modules/http/ modules/http2/ modules/loggers/ modules/mappers/ modules/metadata/ modules/proxy/ mo
On Mon, Nov 23, 2015 at 3:05 PM, Jim Jagielskiwrote: > > That's cheating :) Yeah, reverted (r1715869) and re-committed (r1715876) with no functional change. Thanks for catching!
Re: svn commit: r1715859 - /httpd/httpd/trunk/include/httpd.h
On Mon, Nov 23, 2015 at 9:58 AM,wrote: > Author: jim > Date: Mon Nov 23 15:58:25 2015 > New Revision: 1715859 > > URL: http://svn.apache.org/viewvc?rev=1715859=rev > Log: > we just worry about "equality" with this implementation... > So it's not a "real" strcasecmp replacement. > > Modified: > httpd/httpd/trunk/include/httpd.h > > Modified: httpd/httpd/trunk/include/httpd.h > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/include/httpd.h?rev=1715859=1715858=1715859=diff > > == > --- httpd/httpd/trunk/include/httpd.h (original) > +++ httpd/httpd/trunk/include/httpd.h Mon Nov 23 15:58:25 2015 > @@ -2442,9 +2442,8 @@ AP_DECLARE(int) ap_array_str_contains(co > * Known-fast version of strcasecmp(): ASCII case-folding, POSIX compliant > * @param s1 The 1st string to compare > * @param s2 The 2nd string to compare > - * @return integer greater than, equal to, or less than 0, depending on > - * if s1 is lexicographically greater than, equal to, or less > - * than s2 ignoring case. > + * @return 0 if s1 is lexicographically equal to s2 ignoring case; > + * non-0 otherwise. > */ > AP_DECLARE(int) ap_casecmpstr(const char *s1, const char *s2); > > @@ -2453,9 +2452,8 @@ AP_DECLARE(int) ap_casecmpstr(const char > * @param s1 The 1st string to compare > * @param s2 The 2nd string to compare > * @param n Maximum number of characters in the strings to compare > - * @return integer greater than, equal to, or less than 0, depending on > - * if s1 is lexicographically greater than, equal to, or less > - * than s2 ignoring case. > + * @return 0 if s1 is lexicographically equal to s2 ignoring case; > + * non-0 otherwise. > */ > AP_DECLARE(int) ap_casecmpstrn(const char *s1, const char *s2, apr_size_t > n); > Howso? The implementation does provide ASCII numeric-alpha ordering.
Re: strncasecmp
I just made a small application which takes as command line parameters the number of iteration to run, which version of the algorithm to use, the 2 strings to compare and the length to compare (or 0 for the non 'n' versions) Compiled using gcc -O3 test.c Tested using linux:~/Code_Source$ time ./a.out 1 1 xcxcxcxcxcxcxcxcxcxcwwaa xcxcxcxcxcxcxcxcxcxcwwaa 0 Optimized (nb=1, len=0) res = 0 real0m4.193s user0m4.192s sys0m0.000s linux:~/Code_Source$ time ./a.out 0 1 xcxcxcxcxcxcxcxcxcxcwwaa xcxcxcxcxcxcxcxcxcxcwwaa 0 (nb=1, len=0) res = 0 real0m1.708s user0m1.704s sys0m0.000s See atatchement. CJ Le 23/11/2015 21:33, Yann Ylavic a écrit : Hi Christophe, On Mon, Nov 23, 2015 at 9:12 PM, Christophe JAILLETwrote: I tried to do some but the benefit of the optimized version is not that clear, at least on my system: gcc 5.2.1 Linux linux 4.2.0-18-generic #22-Ubuntu SMP Fri Nov 6 18:25:50 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux Unfortunately, gcc 5.2.1 (i.e. latest compilers' versions) are not widely used... Did you try a code like ap_proxy_port_of_scheme() with values which are unknown schemes? Or even worse cases, with similarly chained strcasecmp() looking for eg. "httpx" in something like {"httpa", "httpb", "httpc", ..., "httpw"}? Regards, Yann. #include #include #include #include /* * Provide our own known-fast implementation of str[n]casecmp() * NOTE: ASCII only! */ static const unsigned char ucharmap[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; int ap_strcasecmp(const char *s1, const char *s2) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (ucharmap[*ps1] == ucharmap[*ps2++]) { if (*ps1++ == '\0') { return (0); } } return (ucharmap[*ps1] - ucharmap[*--ps2]); } int ap_strncasecmp(const char *s1, const char *s2, int n) { const unsigned char *ps1 = (const unsigned char *) s1; const unsigned char *ps2 = (const unsigned char *) s2; while (n--) { if (ucharmap[*ps1] != ucharmap[*ps2++]) { return (ucharmap[*ps1] - ucharmap[*--ps2]); } if (*ps1++ == '\0') { break; } } return (0); } #define PROG argv[0] #define METHOD argv[1] #define NB argv[2] #define S1 argv[3] #define S2 argv[4] #define LEN argv[5] /* The ++ are here to try to prevent some optimization done by gcc */ #define FOR for (i=0; i S1 S2 \n", PROG); return 0; } len = atoi(LEN); nb = atoi(NB); if (*METHOD == '0') { printf(" (nb=%d, len=%d)\n", nb, len); if (len == 0) { FOR { /* really use the result of the function */ res |= strcasecmp(S1, S2); } } else { FOR { res |= strncasecmp(S1, S2, len); } } } else { printf("Optimized (nb=%d, len=%d)\n", nb, len); if (len == 0) { FOR {