digitalmars.D - A better std.string.replace?
- Chris Sauls (89/89) Jul 20 2005 I cooked up this program originally just to test the little 'Timer' clas...
- Burton Radons (15/21) Jul 20 2005 You're getting the speed benefits from using out because you made a
- Chris Sauls (13/24) Jul 20 2005 I'll be darned... this is why I shouldn't code at 4 in the morning... F...
- Ben Hinkle (7/29) Jul 20 2005 Since a common case would be that from.length == to.length it might be w...
- Burton Radons (7/45) Jul 20 2005 That's true. I get these results when I do that:
I cooked up this program originally just to test the little 'Timer' class I made for myself, and wound up with something interesting. I tried to write a "better" version of std.string.replace, and compared their run times. I made two versions of mine, one of them using an inout parameter. And I timed calling it as a "pseudo-member" function (aka: arr.func()). These were my results: [Timer] 'replace' benchmarks: Begin [Timer] std.string.replace: Begin [Timer] std.string.replace: 20.66000 [Timer] myReplace: Begin [Timer] myReplace: 17.02000 [Timer] myReplaceIO: Begin [Timer] myReplaceIO: 13.85000 [Timer] myReplaceIO pseudo-member: Begin [Timer] myReplaceIO pseudo-member: 13.62000 [Timer] 'replace' benchmarks: 65.15000 I note four things here. First, that my timer seems to be working. That's good for me, but nothing exciting. Second, that my cheap and cheesy replace function actually seems to be a little faster. Third, that using an inout parameter has made it even faster. And fourth, that for some reason the pseudo-member invocation sometimes clocks even faster. Draw your own conclusions. Complete source of the test program follows. -- Chris Sauls "This+is+just+your+ordinary+run+of+the+mill+sentence.";
Jul 20 2005
Chris Sauls wrote:I cooked up this program originally just to test the little 'Timer' class I made for myself, and wound up with something interesting. I tried to write a "better" version of std.string.replace, and compared their run times. I made two versions of mine, one of them using an inout parameter. And I timed calling it as a "pseudo-member" function (aka: arr.func()). These were my results:You're getting the speed benefits from using out because you made a mistake in myReplace - you call it once but use std.string.replace for the reverse call. Fixing that makes them take identical times. Yours does use less memory than std.string.replace in most cases. Funny. It can be made slightly faster by avoiding a scan later on, but that wouldn't show up on any but seriously damaged tests. I made a recursive version that makes only one allocation. My results were: [Timer] std.string.replace: 3.4850 [Timer] myReplace: 2.3590 [Timer] replace_recursive: 1.9530 [Timer] 'replace' benchmarks: 7.7970 20% isn't good enough to merit a strict but unknowable, environment-defined limit on how many matches it can take, in my opinion. I think std.string.replace should be swapped with your function.
Jul 20 2005
Burton Radons wrote:You're getting the speed benefits from using out because you made a mistake in myReplace - you call it once but use std.string.replace for the reverse call. Fixing that makes them take identical times.I'll be darned... this is why I shouldn't code at 4 in the morning... Fixing that gave me these times: [Timer] std.string.replace: 20.60000 [Timer] myReplace: 13.62000 [Timer] myReplaceIO: 13.79000 [Timer] myReplaceIO pseudo-member: 13.68000 [Timer] 'replace' benchmarks: 61.69000 So yes, the regular myReplace is definitely quicker. I thought it seemed a little odd the other way around. Although I'm still curious as to why the pseudo-member syntax is clocking slightly faster than the normal invocation.I made a recursive version that makes only one allocation. My results were: [Timer] std.string.replace: 3.4850 [Timer] myReplace: 2.3590 [Timer] replace_recursive: 1.9530 [Timer] 'replace' benchmarks: 7.7970w00t. Share? -- Chris Sauls
Jul 20 2005
"Burton Radons" <burton-radons smocky.com> wrote in message news:dbm52s$k37$1 digitaldaemon.com...Chris Sauls wrote:Since a common case would be that from.length == to.length it might be worth putting in the optimization that would only need one allocation (ie - if there are any matches, dup and copy 'to' in place of 'from' repeatedly) and use the split/join for the general case. I have no idea what the performance would end up being.I cooked up this program originally just to test the little 'Timer' class I made for myself, and wound up with something interesting. I tried to write a "better" version of std.string.replace, and compared their run times. I made two versions of mine, one of them using an inout parameter. And I timed calling it as a "pseudo-member" function (aka: arr.func()). These were my results:You're getting the speed benefits from using out because you made a mistake in myReplace - you call it once but use std.string.replace for the reverse call. Fixing that makes them take identical times. Yours does use less memory than std.string.replace in most cases. Funny. It can be made slightly faster by avoiding a scan later on, but that wouldn't show up on any but seriously damaged tests. I made a recursive version that makes only one allocation. My results were: [Timer] std.string.replace: 3.4850 [Timer] myReplace: 2.3590 [Timer] replace_recursive: 1.9530 [Timer] 'replace' benchmarks: 7.7970 20% isn't good enough to merit a strict but unknowable, environment-defined limit on how many matches it can take, in my opinion. I think std.string.replace should be swapped with your function.
Jul 20 2005
Ben Hinkle wrote:"Burton Radons" <burton-radons smocky.com> wrote in message news:dbm52s$k37$1 digitaldaemon.com...That's true. I get these results when I do that: [Timer] replace_new: 2.3440 (baseline) [Timer] std.string.replace: 7.1870 (0.3261 vs baseline) [Timer] myReplace: 4.7660 (0.4918 vs baseline) [Timer] replace_recursive: 3.8130 (0.6147 vs baseline) [Timer] 'replace' benchmarks: 18.1100 (0.1294 vs baseline)Chris Sauls wrote:Since a common case would be that from.length == to.length it might be worth putting in the optimization that would only need one allocation (ie - if there are any matches, dup and copy 'to' in place of 'from' repeatedly) and use the split/join for the general case. I have no idea what the performance would end up being.I cooked up this program originally just to test the little 'Timer' class I made for myself, and wound up with something interesting. I tried to write a "better" version of std.string.replace, and compared their run times. I made two versions of mine, one of them using an inout parameter. And I timed calling it as a "pseudo-member" function (aka: arr.func()). These were my results:You're getting the speed benefits from using out because you made a mistake in myReplace - you call it once but use std.string.replace for the reverse call. Fixing that makes them take identical times. Yours does use less memory than std.string.replace in most cases. Funny. It can be made slightly faster by avoiding a scan later on, but that wouldn't show up on any but seriously damaged tests. I made a recursive version that makes only one allocation. My results were: [Timer] std.string.replace: 3.4850 [Timer] myReplace: 2.3590 [Timer] replace_recursive: 1.9530 [Timer] 'replace' benchmarks: 7.7970 20% isn't good enough to merit a strict but unknowable, environment-defined limit on how many matches it can take, in my opinion. I think std.string.replace should be swapped with your function.
Jul 20 2005