Jump to content

Mike Torrettinni

Members
  • Content Count

    1509
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by Mike Torrettinni

  1. What about enums? Like TContactAddressType = (caBusiness, caHome, caPublic) or TmyContactAddressType= (mycaBusiness, mycaHome, mycaPublic)?
  2. I like this 'feature' too. Imagine you would need to have a list of all definitions from all Delphi units (+all 3rd party code you use) to be able to create your own unique names. that would be crazy hard to find unique names. What would happen if you have your own TCustomizedPanel and use it all over your project... then Delphi adds same name to their code base. Or any other 3rd party code you want to use, ads it in next update. I think the full qualified name or unit used last in uses clause if good tradeoff.
  3. Mike Torrettinni

    Delphi Native Code: Fast or Reliable?

    I only remember such issue with splash screen, but then implemented it right and all was good. Do you remember what was the cause in your case?
  4. Mike Torrettinni

    Delphi Native Code: Fast or Reliable?

    I just remembered that with one of the first versions I was asked why am I storing user data in Registry and not INI file.I don't remember their reasoning, but I do remember looking into if Windows is getting ready to remove Registry. That would be a breaking change also for Delphi programs, I guess. Luckily they didn't do it. That's exactly what those developers were expecting, to have user INI file right there with exe. I guess this was in Windows XP era.
  5. Just a quick update on a progress of my code: If we use Pos before StringReplace, because actual string replacement is done rarely and not every time this method is called, we can squeeze a little more performance if we move StringReplace out of the current method: procedure DoStringReplace(var aStr: string; const aOldStr, aNewStr: string); begin aStr := StringReplace(aStr, aOldStr, aNewStr, [rfReplaceAll]); end; function PrepareStr(const aStr: string): string; begin Result := aStr; ... if Pos(cInvalidSubStr, Result) > 0 then DoStringReplace(Result, cInvalidSubStr, ''); end; In this case the slow safe string handling stuff is done in DoStringReplace method. I guess this is the similar optimization trick that many use by moving rare error report message to another method, instead of using string concatenation in the method where error is raised. We just need to make sure we don't make DoStringReplace inlined, then all performance gain is lost. It took me a while to find that out 😉
  6. Yes. I have numerous checks for what first char is, in different parsers, so I'm wrapping into single method where I check for empty string first.
  7. During routine profiling I noticed a function that gets called 1mio+ times and I wanted to look into it, even though it's only 0.24% of total execution time. So, not a bottleneck, but still wanted to see is there anything need to be addressed. Here is example that imitates a real function: var flag: boolean = true; function ProcessString(const aStr: string): string; var s: string; i: integer; b: boolean; begin if flag then Exit(aStr); // dummy code to use the local variables s := aStr; i := Length(s); b := i = 1; if b then Result := aStr else Result := s; end; As this function will always return string and exit, the same does my real function in 99.9% cases - in only 0.01% cases executes the lower part of the function. If I split functions to this: function ProcessStringOLD(const aStr: string): string; var s: string; i: integer; b: boolean; begin s := aStr; i := Length(s); b := i = 1; if b then Result := aStr else Result := s; end; function ProcessStringNew(const aStr: string): string; begin if flag then Exit(aStr) else Result := ProcessStringOLD(aStr); end; In this case, the new ProcessStringNew is 25% faster, because it never executes ProcessStringOLD - make sense. But if I set the flag = false, then of course ProcessStringNew is slower vs original ProcessString, but only by 7%. So new changes result in: 25% faster in 99.9% and 7% slower in 0.01%. Does this micro optimization makes sense? I assume a few little changes like this across in multiple functions, and it could save some valuable execution time, >1%.
  8. A bad scenario in my code reminded me of this thread, so I re-read it to be sure I'm not missing out anything important. Very useful conclusion! I had an example of some old string manipulation method which I replaced with better one, and I set it up like this - not sure why I used this wrong approach: procedure Work(var aStr:string); var vTmp1, vTmp2: string; begin WorkBetter(aStr); Exit; // here was old stuff that handled string slower than in WorkBetter ... end; When looking at profiling results and the code I was sure this method can't be result of any performance bottle-neck, because it doesn't even touch the slow code! Well, of course I was wrong because it still handles 2 local string vars. Thanks again!
  9. This was very productive weekend! A lot of refactoring done. Even though only a few instances need to be performant, it was good exercise and now I have 1 common function that handles all these comparisons how strings start. And if newer Delphi version eventually implements better (faster) option, I can easily make a change. Clean, refactored and optimized piece of code. Thanks!
  10. I guess comparing just 1 char at beginning is better to do with Char: function StrStartsWith(const aStr, aSubStr: string): boolean; inline; overload; function StrStartsWith(const aStr:string; const aChar: Char): boolean; inline; overload; function StrStartsWith(const aStr, aSubStr: string): boolean; inline; overload; var c, vLenStr, vLenSubStr: integer; begin vLenStr := Length(aStr); vLenSubStr := Length(aSubStr); if vLenStr < vLenSubStr then Exit(false); if vLenStr = vLenSubStr then Exit(aStr = aSubStr); for c := 1 to Length(aSubStr) do if aStr[c] <> aSubStr[c] then Exit(false); Result := True; end; function StrStartsWith(const aStr:string; const aChar: Char): boolean; inline; overload; begin if aStr = '' then Exit(false); Result := aStr[1] = aChar; end;
  11. Ha ha, I even use a few of LeftStr, to compare the beginning of a string. But it uses Copy, so it's same performance, Talk about the need for refactoring weekend 😉
  12. OK, there is problem with my test case: if I define consts as strings then TStringHelper.StartsWith is much faster! Substring exists at the start: Short string: const only: StartsWith: 505 // slow when consts are not of defined type StartsStr: 795 StartsWithStr: 53 const string: StartsWith: 65 // much faster when consts defined as string! StartsStr: 785 StartsWithStr: 64
  13. Interesting inefficiency of TStringHelper.StartsWith and StartsStr when string and substring are the same: Substring is same as string: Short string (20 chars): StartsWith: 206 StartsStr: 1113 // ! StartsWithStr: 46 StartsWithStr2: 42 Long string (238 chars): StartsWith: 1358 // ! StartsStr: 4948 // ! StartsWithStr: 45 StartsWithStr2: 40 I guess they don't check for len(str) = len(substr) or str=substr.
  14. I setup this function: function StartCharByChar(const aSubString, aString: string): boolean; var c: integer; begin Result := True; for c := 1 to Length(aSubString) do if aString[c] <> aSubString[c] then Exit(false); end; And it wins! 😉 Substring exists at the start: Short string: Copy: 169 MidStr: 182 StartsWith: 515 StartsStr: 784 StartCharByChar: 41 // :) Long string: Copy: 176 MidStr: 191 StartsWith: 518 StartsStr: 846 StartCharByChar: 115 // :) Substring NOT exists at the start: Short string: Copy: 166 MidStr: 183 StartsWith: 515 StartsStr: 876 StartCharByChar: 33 // :) Long string: Copy: 171 MidStr: 184 StartsWith: 507 StartsStr: 885 StartCharByChar: 33 // :)
  15. I'm not so experienced in analyzing Delphi sources to be able to assess what is optimized and what is wasting resources. In my code I mostly look for short strings at the beginning, so perhaps my test cases are just right for Copy to be fastest and that will not be the case with 'better' examples. I use 10.2.3 version.
  16. Mike Torrettinni

    Free EurekaLog license drawing

    I guess they forgot to update on results all the forums they posted this. Anybody interested on results: https://blog.eurekalog.com/2021/02/eurekalog-2020-survey-results.html
  17. Mike Torrettinni

    Fast stable sorting routines

    Is there a download link or each file has to be downloaded individually?
  18. Interesting. Publish this as your own thread so it can bookmarked, I bookmark anything related to performance.
  19. One example I didn't test: if substring is at the end of string, so that Pos runs the longest: Long string Find AtTheEnd + Pos: 2938 Long string Find AtTheEnd - Pos: 2298 In this case using Pos adds 32% of time. Which is quite substantial, but in my real data this happens in less than 0.01% cases, so not really valid case.
  20. Data could be entity names, descriptions, notes, comments... free text, in any language. I assumed lorem ipsum is good to be used for such test cases.
  21. How should I phrase it that this is referencing a comment about redundant Pos with StringReplace and not that I'm looking for a solution for the original SO question?
  22. I referenced exact comment in the SO question which I investigated and prepared MCVE to confirm, or that someone shows my test case is wrong, or what is missing. That was original post. Then I analyzed real data to try to get as close to it as possible, and second test case shows better representation of real data. Or are you suggesting I post my project source and customer data?
×