-
Content Count
3586 -
Joined
-
Last visited
-
Days Won
176
Everything posted by David Heffernan
-
Casting pointer to TBytes
David Heffernan replied to Jacek Laskowski's topic in RTL and Delphi Object Pascal
You need to have a function that accepts a pointer to the byte array, and its length. Then you can pass your raw memory pointer, or pass Pointer(Bytes), Length(Bytes) when you have a TBytes to hand. -
Casting pointer to TBytes
David Heffernan replied to Jacek Laskowski's topic in RTL and Delphi Object Pascal
That's not an array of TBytes. It's not clear to me what your question is yet. -
Mapping or Cartography, that's the question
David Heffernan replied to FPiette's topic in General Help
Which can lead to being dropped from search results for manipulation and BMW found out a few years ago. -
Mapping or Cartography, that's the question
David Heffernan replied to FPiette's topic in General Help
I'm not convinced by what Diego says. Seems unlikely to me that cartography is a search keyword that will work for you. I wouldn't like to make suggestions, don't know what your software is. All I am saying is that if your software isn't for the purpose of creating maps then it isn't cartography. -
Mapping or Cartography, that's the question
David Heffernan replied to FPiette's topic in General Help
As an English speaker and an orienteer (course d'orientation en Français) I am clear that cartography is the act of surveying and creating a map. I don't think you want to use that word for your software as you have described it here. -
It is a class method. Use the class as the subject of the method call.
-
Micro optimization: String starts with substring
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
This seems pointless to me. It's important to test this in the real setting. What timings do you have? -
Micro optimization: String starts with substring
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
What are your timings like in the real world setting? -
Micro optimization: String starts with substring
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I don't see any reason to check that. We've long since solved this. -
Micro optimization: String starts with substring
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Not if the search string is longer than the other string. Then it's a buffer overrun. Use the version from my post. -
Micro optimization: String starts with substring
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
{$APPTYPE CONSOLE} uses System.SysUtils, System.Diagnostics, System.StrUtils; function MyStartsWith(const SearchText, Text: string): Boolean; var Index, SearchTextLen: Integer; begin SearchTextLen := Length(SearchText); if SearchTextLen>Length(Text) then begin Result := False; Exit; end; for Index := 1 to SearchTextLen do if Text[Index]<>SearchText[Index] then begin Result := False; Exit; end; Result := True; end; const cMaxLoop = 10000000; cText = 'Error: 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.'; cTextNoHits = '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.'; cStartsWithShort = 'E'; cStartsWithLong = 'Error:'; var vSW: TStopWatch; i, vLen: integer; hitCount: Integer; vResult: boolean; begin Writeln('Substring exists at the start:'); // Short string Writeln('Short string:'); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if Copy(cText, 1, Length(cStartsWithShort)) = cStartsWithShort then Inc(hitCount); Writeln(' Copy: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MidStr(cText, 1, Length(cStartsWithShort)) = cStartsWithShort then Inc(hitCount); Writeln(' MidStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if cText.StartsWith(cStartsWithShort) then Inc(hitCount); Writeln(' StartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if StartsStr(cStartsWithShort, cText) then Inc(hitCount); Writeln(' StartsStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MyStartsWith(cStartsWithShort, cText) then Inc(hitCount); Writeln(' MyStartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); // Long string Writeln('Long string:'); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if Copy(cText, 1, Length(cStartsWithLong)) = cStartsWithLong then Inc(hitCount); Writeln(' Copy: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MidStr(cText, 1, Length(cStartsWithLong)) = cStartsWithLong then Inc(hitCount); Writeln(' MidStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if cText.StartsWith(cStartsWithLong) then Inc(hitCount); Writeln(' StartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if StartsStr(cStartsWithLong, cText) then Inc(hitCount); Writeln(' StartsStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MyStartsWith(cStartsWithLong, cText) then Inc(hitCount); Writeln(' MyStartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); Writeln; // Text DEOS NOT start with selected string Writeln('Substring NOT exists at the start:'); // Short string Writeln('Short string:'); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if Copy(cTextNoHits, 1, Length(cStartsWithShort)) = cStartsWithShort then Inc(hitCount); Writeln(' Copy: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MidStr(cTextNoHits, 1, Length(cStartsWithShort)) = cStartsWithShort then Inc(hitCount); Writeln(' MidStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if cTextNoHits.StartsWith(cStartsWithShort) then Inc(hitCount); Writeln(' StartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if StartsStr(cStartsWithShort, cTextNoHits) then Inc(hitCount); Writeln(' StartsStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MyStartsWith(cStartsWithShort, cTextNoHits) then Inc(hitCount); Writeln(' MyStartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); // Long string Writeln('Long string:'); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if Copy(cTextNoHits, 1, Length(cStartsWithLong)) = cStartsWithLong then Inc(hitCount); Writeln(' Copy: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MidStr(cTextNoHits, 1, Length(cStartsWithLong)) = cStartsWithLong then Inc(hitCount); Writeln(' MidStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if cTextNoHits.StartsWith(cStartsWithLong) then Inc(hitCount); Writeln(' StartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if StartsStr(cStartsWithLong, cTextNoHits) then Inc(hitCount); Writeln(' StartsStr: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); hitCount := 0; vSW := TStopWatch.StartNew; for i := 1 to cMaxLoop do if MyStartsWith(cStartsWithLong, cTextNoHits) then Inc(hitCount); Writeln(' MyStartsWith: ' + vSW.ElapsedMilliseconds.ToString, ' ', hitCount); readln; end. Copy is clearly a shocker of an idea for this use. heap allocation!! Really?!!! And the other functions seem really slow. A simple for loop is around 10 times faster. I didn't capture any timings, but it's easy to do it on your machine. I also addressed a couple of issues with your benchmark code. I don't believe this is a bottleneck in your program, but you love premature optimisation with a rarely seen passion. -
Make a minimal reproduction
-
Works fine here. Try it with a plain vanilla TListView to rule out the changes you have made.
-
Put the code that you don't want clients to have access to in a separate module/library/web service/etc. that is only available on your intranet.
-
TimSort for Delphi without Generics
David Heffernan replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Bookmark this: https://softwareengineering.stackexchange.com/a/80092/14432 -
The question really is how much security you need. What would be the consequence of somebody outside your organisation getting access to this functionality?
-
TimSort for Delphi without Generics
David Heffernan replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Sorting a reversed array is 100% from the real world. In a UI where you sort by a column ascending, and then sort by the same column descending. -
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Earlier in the thread you said that the original problem from the SO question was driving this topic. -
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Sample data might be useful. I'm amazed that you don't see the huge difference between your SO question and the code in this post. In this post you make one replacement. In the SO post you make five. That's the key issue here. And in five years you have not appreciated it. -
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
The code in this post doesn't accurately represent the code in your app which calls StringReplace repeatedly on the same string. As per the SO question. -
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Your benchmarks are bogus because the real code replaces multiple strings. It is simple to make this code at least three times faster in the real setting. -
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I did -
OK. In that case I definitely recommend the neslib parser. I myself use libyaml2 but neslib is good.
-
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Read back in the thread. He says that it's the same code as the SO question that he is trying to make go faster. -
Micro optimization: use Pos before StringReplace
David Heffernan replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
The code is the code in the SO question which calls StringReplace multiple times.