http://qs321.pair.com?node_id=11119949


in reply to Re^4: A locale independent sprintf?
in thread A locale independent sprintf?

Interesting and surprising results. You said "the order does switch between runs" but I don't see that in any of the results you posted; there is quite a substantial fluctuation though (11% to 65%).

I tried with something closer to the code in perlperf to which I linked earlier. I have Cygwin on Win10. I also have Perlbrew. I originally ran under 5.32.0; then switched to 5.30.0 to match your version — there were no significant differences in results. As my locale uses '.', not ',', I simply swapped the substitution (y/./,/ instead of y/,/./). Here's the code I used:

#!/usr/bin/env perl use 5.016; use warnings; use Benchmark 'cmpthese'; use POSIX 'locale_h'; say POSIX::setlocale(LC_NUMERIC); say sprintf('%.2g', 3.14); say sprintf('%.2g', 3.14) =~ s/\./,/r; say sprintf('%.2g', 3.14) =~ y/./,/r; cmpthese 0 => { sprintf => sub { my $str = sprintf('%.2g', 3.14); return $str; }, y_sprintf => sub { my $str = sprintf('%.2g', 3.14) =~ y/./,/r; ret +urn $str; }, s_sprintf => sub { my $str = sprintf('%.2g', 3.14) =~ s/\./,/r; re +turn $str; }, };

Here's a typically result:

$ ./pm_11119934_bench_locale_s_y.pl en_AU.UTF-8 3.1 3,1 3,1 Rate s_sprintf y_sprintf sprintf s_sprintf 2940825/s -- -46% -85% y_sprintf 5493603/s 87% -- -72% sprintf 19713322/s 570% 259% --

I ran it 5 times with 5.32.0, then 5 times with 5.30.0. The 87% in the representative run only ranged between 85% and 89% in all runs. So, I'm getting y/// almost twice as fast as s///; compared with your s/// being variably faster than y///.

I added in the 'use strict; use warnings;' which you had. Now the results varied (85% 88% 21% 71% 75%) but 'y_sprintf' was still always faster. (I suspect the 21% is bogus — perhaps some short-lived background process fired up at that time.)

I then added the 'use locale;' that you had and this substantially slowed down processing: 'y_sprintf' was still faster than 's_sprintf' but I wouldn't say significantly so (5% 1% 7% 12% 8%).

I next replaced my subs with your strings (',' and '.' swapped as before). Again, 'y_sprintf' was faster and this time closer to, albeit more spread out than, my original results (75% 89% 87% 92% 90%).

So, I can't replicate your s/// being faster than y///; all my tests indicated that the opposite was the case. I think the addition of 'use strict; use warnings;' was probably unnecessary for the benchmark; and perhaps a distraction. I don't know enough about locales to confidently comment; however, it would seem that if you can live without 'use locale;' that would be a good thing (its doco, locale, has warnings about its use). Perhaps try with some of my variations to see if you get different results.

— Ken