Mike Torrettinni
Members-
Content Count
1509 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Mike Torrettinni
-
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I don't understand, what is missing that would be MCVE? I have description, results and code, what could I include to improve the test case? -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I checked my string replacements in more details and on average there are 3 replacements in long strings. So, I included test with 3 replacement and the difference using Pos before StringReplace or without Pos is even smaller, 1% only, while when substring is not found not using Pos adds 100%+ to the execution time. Short string Find + Pos: 1322 Short string Find - Pos: 1275 Short string 3x Find + Pos: 1504 Short string 3x Find - Pos: 1482 Short string NO Find + Pos: 98 Short string NO Find - Pos: 686 Long string Find + Pos: 2525 Long string Find - Pos: 2322 Long string 3x Find + Pos: 2609 Long string 3x Find - Pos: 2517 Long string NO Find + Pos: 660 Long string NO Find - Pos: 1452 So, using Pos before StringReplace saves a lot of time, unless we are sure that the substring exists, then it adds some time, depending on string length. program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Diagnostics; const cMaxLoop = 10000000; cShortStr = 'Testing string magna.'; cShortStr3x = 'Testmag strmaging magna.'; cLongStr = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'; cLongStr3x = 'Lorem ipsum dolor sit ametmag, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequatmag.'; cFind = 'mag'; cNoFind = 'mga'; cReplace = 'X'; var vNewStr: string; vSW: TStopWatch; c: Integer; procedure TestShort_Find; begin vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do if Pos(cFind, cShortStr) > 0 then vNewStr := StringReplace(cShortStr, cFind, cReplace, [rfReplaceAll]); Writeln('Short string Find + Pos: ' + vSW.ElapsedMilliseconds.ToString); vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do vNewStr := StringReplace(cShortStr, cFind, cReplace, [rfReplaceAll]); Writeln('Short string Find - Pos: ' + vSW.ElapsedMilliseconds.ToString); end; procedure TestShort_NoFind; begin vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do if Pos(cNoFind, cShortStr) > 0 then vNewStr := StringReplace(cShortStr, cNoFind, cReplace, [rfReplaceAll]); Writeln('Short string NO Find + Pos: ' + vSW.ElapsedMilliseconds.ToString); vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do vNewStr := StringReplace(cShortStr, cNoFind, cReplace, [rfReplaceAll]); Writeln('Short string NO Find - Pos: ' + vSW.ElapsedMilliseconds.ToString); end; procedure TestShort_Find3x; begin vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do if Pos(cFind, cShortStr3x) > 0 then vNewStr := StringReplace(cShortStr3x, cFind, cReplace, [rfReplaceAll]); Writeln('Short string 3x Find + Pos: ' + vSW.ElapsedMilliseconds.ToString); vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do vNewStr := StringReplace(cShortStr3x, cFind, cReplace, [rfReplaceAll]); Writeln('Short string 3x Find - Pos: ' + vSW.ElapsedMilliseconds.ToString); end; procedure TestLong_Find; begin vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do if Pos(cFind, cLongStr) > 0 then vNewStr := StringReplace(cLongStr, cFind, cReplace, [rfReplaceAll]); Writeln('Long string Find + Pos: ' + vSW.ElapsedMilliseconds.ToString); vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do vNewStr := StringReplace(cLongStr, cFind, cReplace, [rfReplaceAll]); Writeln('Long string Find - Pos: ' + vSW.ElapsedMilliseconds.ToString); end; procedure TestLong_NoFind; begin vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do if Pos(cNoFind, cLongStr) > 0 then vNewStr := StringReplace(cLongStr, cNoFind, cReplace, [rfReplaceAll]); Writeln('Long string NO Find + Pos: ' + vSW.ElapsedMilliseconds.ToString); vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do vNewStr := StringReplace(cLongStr, cNoFind, cReplace, [rfReplaceAll]); Writeln('Long string NO Find - Pos: ' + vSW.ElapsedMilliseconds.ToString); end; procedure TestLong_Find3x; begin vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do if Pos(cFind, cLongStr3x) > 0 then vNewStr := StringReplace(cLongStr3x, cFind, cReplace, [rfReplaceAll]); Writeln('Long string 3x Find + Pos: ' + vSW.ElapsedMilliseconds.ToString); vSW := TStopWatch.StartNew; for c := 1 to cMaxLoop do vNewStr := StringReplace(cLongStr3x, cFind, cReplace, [rfReplaceAll]); Writeln('Long string 3x Find - Pos: ' + vSW.ElapsedMilliseconds.ToString); end; begin TestShort_Find; TestShort_Find3x; TestShort_NoFind; TestLong_Find; TestLong_Find3x; TestLong_NoFind; Readln; end. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yes, I put it on ToDo list to revisit - 5 years ago when I tried to implement it it was 10x slower than normal StringReplace call, perhaps because they way I was concatenation strings. Now I can probably improve it, I just need to book the time. Good thing is nobody is disputing that Pos is good improvement to use with StringReplace, when we don't know if call is actually needed or not - if sub string is in the string. Of course for repetitive calls, like in my case. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I tried to customize the StringReplace to use Pos and exit asap if string is not found within, but I broke something for other cases, so I had to give up 🙂 -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I used similar code for replacing strings in pre 2009, but at that time the performance was not my main focus. I guess I should have started at that time and perhaps I wouldn't deal with this now 😉 -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
You are talking about pre 2009 versions? -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yes, I wasn't successful in creating final version of multiple string replace function in one go. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Based on my Delphi knowledge this would probably be way more expensive (in hours, days), and highly likely it will not result in 'faster in all cases'. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yes, of course. Currently working on this part of the code that is a bottleneck. Want to make sure it doesn't regress, so every step is measured and evaluated. The fact is that only a few customers have data that this code is needed. So, it's a tradeoff between slower by 5% for 5% cases and 50-80% faster for 95% cases. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I guess Pos before StringReplace is already an improvement, when substring is not found but we don't know it. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Just did the search through my code and I only use Pos when dealing with a lot of data, when there is repetitive call to StringReplace. Otherwise not, since the performance is not important. Any recommendations on more efficient function? -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Aha, I just noticed StrigReplace has rfIgnoreCase flag. -
Micro optimization: use Pos before StringReplace
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yes, it doesn't use Pos to check if it needs replacing at all. Which is strange. But that is in Delphi 10.2.3, perhaps newer version has this fixed. Which version of Delphi do you use, does it have Pos check at the beginning? -
Is anybody customizing source editor? I usually just change font, right now using Source code pro, but just realized I can make comments non-italic and solve the years long annoyance with cut of last char 😉 Any other suggestions on small changes that can improve the source editor?
-
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
Ok, this makes sense now. So in terms on warnings: they count number of reported lines since 1 warning is reported on 2 lines. Perhaps a rewording of what is reported on Compile window would be useful. -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
I think we understood original post differently. He reported, questioned how errors are counted. I found similar issue in counting Warnings. Hints look to be OK. If reporting on these numbers is not useful, why is it there then? -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
Well, nobody is suggesting joining the class action suit against Embarcadero for not counting correctly, is just counting, right? How could they mess this up? -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
You are pretty vague here... big picture of what, what are you talking about? -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
You don't read blogs? I like to, usually is condensed topic vs books. -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
Since I prefer short blogs over books, I suggest googling: " is attention to detail useful?" and you will find many blogs and even books that might be helpful to you, in software development and also in life. -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
You don't think it should report 1 Warnings if there is only1 Warning? Why it counts the same warning 2 times? Hints work correct, 1 Hint = 1 reported Hint. -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
Looks like Warnings is off by 1 too - well it counts same Warning 2x: @c0d3r I guess you started the scrutiny of Compile window... looks even more broken, unfortunately I'm using Delphi 10.2.3, I hope newer versions have this improved. -
1 error + 1 error = 3 errors? where is the extra one?
Mike Torrettinni replied to c0d3r's topic in Delphi IDE and APIs
It's the same result in 10.2.3, not sure which version you have. I guess Delphi has it's own broken windows theory 😉 -
Is it really that bad to Use boolean parameters to make your functions do two things?
Mike Torrettinni posted a topic in General Help
Just interested how others view this implementation: processOrder(dontUseWidget: Boolean) { if not dontUseWidget then { processOrderWithWidget(); } else { processOrderWithoutWidget(); } } Nick Hodges describes here: https://medium.com/nickonsoftware/twenty-one-ways-to-be-a-crappy-software-developer-c69e4b39c5df- see #20 Use boolean parameters to make your functions do two things I use such code similar as abode, or in examples like: procedure EnableDisableControls(aEnabled: boolean = True); begin MainForm.Control.Enabled := aEnabled; ... end; and a few other instances. I'm just curious how others see this example, is anybody else using it or is it really that bad example that it should be nuked out of any project? -
Is it really that bad to Use boolean parameters to make your functions do two things?
Mike Torrettinni replied to Mike Torrettinni's topic in General Help
Oh, maybe this should be for Google Translate.