in reply to Re^2: A locale independent sprintf?
in thread A locale independent sprintf?
Using y/,/./, instead of s/,/./, should be faster (see "perlperf: Search and replace or tr"). Obviously, I can't say whether it will be noticeably or usefully faster.
You may want the 'r' modifier. Here's a somewhat fudged example for demonstration purposes:
$ perl -E 'say sprintf("3,%d", 14)' 3,14 $ perl -E 'say sprintf("3,%d", 14) =~ y/,/./' Can't modify constant item in transliteration (tr///) at -e line 1, at + EOF Execution of -e aborted due to compilation errors. $ perl -E 'say sprintf("3,%d", 14) =~ y/,/./r' 3.14
If you try this, I'd be interested in what sort of speed improvement you see.
— Ken
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: A locale independent sprintf?
by swl (Prior) on Jul 29, 2020 at 04:06 UTC | |
Good point. I'll see if I can set up some benchmarking and post the results. Update: Running the code below under ubuntu bash under windows with LC_NUMERIC set to de_DE.iso88591 indicates that s///r is about 20% faster than y//r. Both are in the order of millions per second, though. And as yet another update, the order does switch between runs so it's not a consistent outcome. Results:
Code:
(post was further updated to distinguish results from code) | [reply] [d/l] [select] |
by kcott (Archbishop) on Jul 29, 2020 at 09:05 UTC | |
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:
Here's a typically result:
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 | [reply] [d/l] [select] |
by swl (Prior) on Jul 29, 2020 at 12:18 UTC | |
I neglected to respond to this point in my other post: however, it would seem that if you can live without 'use locale;' that would be a good thing. I'm in full agreement here, and don't use it my own code. It's the side effect it being called in another package (Gtk2 in this case) that triggered the issue with my own system. salva's recommendation of using no locale in 11119943 and 11119948 looks good to me, and I'll be reaching for it next time I strike this issue. | [reply] [d/l] |
by swl (Prior) on Jul 29, 2020 at 11:58 UTC | |
The order did switch a little between runs, but that largely ceased once I stopped fiddling about with other processes while the benchmarks were running. I get the same for a locale using a dot as the decimal separator (same WSL system and perl, and also for Strawberry perl 5.28.1). I'll have to try on a native linux machine. I'm not sure why your results are so different. The results I showed use a de_DE locale, so perhaps there is overhead when locale handling is triggered. There are also noise effects with benchmarking, although the numbers are pretty distinct in this case. It could also just be my system. As for use strict and use warnings, I've been bitten before with string based benchmarking when trying to avoid sub overheads. Taking them out makes no difference to the results (see below, although there is one case where y is faster than s). The underlying benchmark code actually calls no strict before it evals code passed as strings. Note the _doeval call in the code generation when a string is passed. Results without strict and warnings:
| [reply] [d/l] [select] |
by swl (Prior) on Jul 29, 2020 at 05:11 UTC | |
Some extra runs while not interacting with the machine. Perl is 5.30.0 via perlbrew under WSL.
Results:
| [reply] [d/l] [select] |