Mike Torrettinni
Members-
Content Count
1509 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Mike Torrettinni
-
Simple inlined function question
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I'm not sure what more I can write that I didn't put into first post. Aha, I didn't think about the version differences. I use Delphi 10.2.3. Not sure which compiler directives are you referring to, I don't set anything specific, whatever is default in debug, as this is tested in new empty project. -
Simple inlined function question
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Yes, I admit I have a tendency to try optimize sometimes without measuring first. I assume this is what is going on here and of course also my expectation how compiler should work. If I look at simpler example, I can see the compiler generates the same code with or without function call, as expected,: In this simple example of Inc(), the asm code generated is the same: procedure Inc_Inlined(var aValue: integer); inline; begin Inc(aValue); end; procedure TForm2.FormCreate(Sender: TObject); var a: integer; begin a := 0; Inc(a); Inc_Inlined(a); end; And now also with the documentation on inline directive: " The inline directive is a suggestion to the compiler. There is no guarantee the compiler will inline a particular routine, as there are a number of circumstances where inlining cannot be done. The following list shows the conditions under which inlining does or does not occur: Perhaps the documentation could mention that it is also not guaranteed that generated code will be as efficient as if the code was entered instead of function call. Sometimes it will be the same code, sometimes not. -
Simple inlined function question
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Thanks, but in this case I was just looking for some understanding why such difference. This is generic condition used to search the data, repeated across multiple record types. For example searching Project names, Item names, Group names... -
Simple inlined function question
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Oh, sorry I guess I wasn't clear enough of my goal: the loop condition is used in numerous places, so I want to shorten the code and have 1 call to inlined function that replaces all these (same) conditions. I updated the first post. -
Simple inlined function question
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I see. Do you think there is a way to avoid this extra boolean evaluation, perhaps restructuring function? I'm not familiar with asm, but I see a difference in generated asm code between the loops. I have no idea how to interpret the difference, now I assume it could be the extra boolean evaluation you are referring to. -
Simple inlined function question
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Same, loop without call to inlined function is 50% faster. Did you expect different results depending on the order of loops? -
I prepared full example of a problem, but then I tried something different and it seem to be working OK, so, lets try with just quick confirmation: I have interposer for TCard so I can have custom data: TCard = class(Vcl.WinXPanels.TCard) strict private fDataType: TDataType; public property DataType: TDataType read fDataType write fDataType; end; Until today I never needed to create control that has interposer. But today I did and I started like this: and error occurs, of course: var vCard: TCard; ... vCard := CardPanel.AddNewCard; // ERROR: E2010 Incompatible types: 'Unit2.TCard' and 'Vcl.WinXPanels.TCard' vCard.DataType := x; so, I set it up like this - but I need to cast vCard all the time: var vCard: Vcl.WinXPanels.TCard; ... vCard := CardPanel.AddNewCard; // OK TCard(vCard).DataType := x; // BUT NOW I HAVE TO CAST IT ALL THE TIME BUT! now I figured out I can cast just initial CardPanel.AddNewCard line: var vCard: TCard; ... Vcl.WinXPanels.TCard(vCard) := CardPanel.AddNewCard; // OK vCard.DataType := x; // OK This seems correct. Is this the right way to do it? Or am I going into uncharted territory and will probably fail at some other point? Thanks!
-
Update: As suggested, I removed the interposer class and implemented the Frame controller as suggested here: So instead of TCard control to hold custom data to identify which Data Frame it should show, Frame controller is responsible to connect TCard with appropriate Data Frame, so Main Form doesn't communicate with Data Frames anymore, as this is now Frame Controller's job. Works good, I'm happy with the correct solution 🙂
-
I don't understand this CONST record argument behavior
Mike Torrettinni posted a topic in Algorithms, Data Structures and Class Design
I assumed that using const with arguments to methods is best because it reduces the need for safe handling of arguments/prevents copying... But here I have example that the method is still 'safe handling' the const record: In this example the @InitializeRecord is executed at begin, and @FinalizeRecord at end of method: function CheckSubItem(const aSubItem: TSubItem): boolean; begin Result := aSubItem.Name = 'A'; end; function CheckItem(const aItem: TItem): boolean; var i: Integer; begin Result := false; if aItem.SubItems <> nil then for i := 0 to Pred(aItem.SubItems.Count) do begin If CheckSubItem(aItem.SubItems[i]) then // ** THIS CALL ADDS SAFETY HANDLING!? Result := True; end; end; if I have call to CheckSubItem, the CPU view shows: But if I comment the call to CheckSubItem, this this the CPU view for begin/end: Why are there @InitializeRecord and @FinalizeRecord if const is used in both methods. Shouldn't there be none of these calls? -
Is Class with 2 'nested' constructors bad design?
Mike Torrettinni posted a topic in Algorithms, Data Structures and Class Design
I have 2 constructors in my class and Create2WayCompare calls default Create constructor: TINIComparer = class public constructor Create(const aINIFileName1, aINIFileName2: string); overload; constructor Create2WayCompare(const aINIFileName1, aINIFileName2: string); overload; end; constructor TINIComparer.Create2WayCompare(const aINIFileName1, aINIFileName2: string); begin fCompareType := cmt2WayCompare; Create(aINIFileName1, aINIFileName2); end; constructor TINIComparer.Create(const aINIFileName1, aINIFileName2: string); begin fINIFileName1 := aINIFileName1; fINIFileName2 := aINIFileName2; LoadINIFiles; CompareINIFiles; end; // from main form: fINIComparer := TINIComparer.Create2WayCompare(edtINIFilename1.Text, edtINIFilename2.Text); I'm planning to have a few more Create???() constructors that will indicate different class options. This works good, no memory leaks no AV errors. But 2 constructors are executed. Is this OK, just bad design or something is wrong but it didn't show up yet with such a simple class example? -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I didn't know you can use Length on TList (actually works on TList.List) - I assume Length(TList.List) = TList.Capacity, right? I always use Count for TList, Length for Arrays. -
Is Class with 2 'nested' constructors bad design?
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
That's a false goal. Remove that goal from your life. Following it will be making your code worse. I knew somebody already told me this, but I'm glad I found it to stop me going down that path again 🙂 -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
As @Dalija Prasnikar explained sometimes you are not after super-duper micro optimization, but if something is standing out you try with simple optimization. Here is example that triggered this topic: I started with For..in loop and accessing data the 'correct way' (without .List), the method took almost 3s: I changed to for i := 0 to Count - 1, the execution time dropped by 60%: And this is execution time accessing data thought .List: a 99% reduced execution time: The whole method dropped from almost 20% of whole execution process time, to just 0.15%. I would say this a very valid reason to access items directly, through .List. OK, for context, this only came to light after one of the customer's data set came to be 10x bigger than what was thought was the biggest data set. So, the original method was working good and at acceptable performance, but it failed miserably when 1 customer went rogue. -
Adding 'Show All topics' to see all topics in selected forum
Mike Torrettinni replied to Mike Torrettinni's topic in Community Management
If at all possible, I would suggest similar thing to show all posts in a topic. Since some questions become discussions, after 2nd page is really hard to follow, but if all posts are open in single page, it's much easier to read and follow the discussion and different views on topic. -
Thanks guys, good point! The advice comes in at the right time, after discovering TCardPanel still has some quirks in Delphi 10.2.3. and my interposer is just adding on the points of failure.
-
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Aha, yes, it's on. -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
In for loop, I was sure we don't need range checking, right? Of course when iteration is from 0 to Count-1 index, for TList. But, when you are iterating through custom indexes, I assume range checking would be needed - but I don't use TList that way - I have some example for arrays, which first makes sure FromIndex and ToIndex are within Low and High of array. -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Thanks, yes, in this case I always access valid index. -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
What would be a situation where accessing through .List is not advisable? I assume if I access TList, I control the content anyway, so I assume .List should be safe in all cases, no? -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I reviewed my code using TList and I used .List only when changing the content. All works good until big data set comes into play and then using non-direct access can be a real bottleneck. This also applies to the simpler TList<string> not only for TList<record>. So, from now on I will always use direct access through .List. -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
You are right! If I do this: If CheckSubItem(aItem.SubItems.List[i]) then there is no Initialize/FinalizeRecord anymore. Such a hidden little detail, important detail 🙂 -
I don't understand this CONST record argument behavior
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
No, simple records. Here is the rest of the example details: type TSubItem = record ID: integer; Name: string; end; TItem = record ID: integer; Name: string; SubItems: TList<TSubItem>; end; ... procedure TForm2.FormCreate(Sender: TObject); var vItem: TItem; vSubItem: TSubItem; begin // test data vItem.SubItems := TList<TSubItem>.Create; vSubItem.Name := 'A'; vItem.SubItems.Add(vSubItem); if CheckItem(vItem) then showmessage('A found'); end; -
Couple IDE filtering feature requests, vote if care
Mike Torrettinni replied to Tommi Prami's topic in Delphi IDE and APIs
Great! I'm for any improvement to Structure view. -
If you still need it, you can achieve blinking effect with CSS: https://www.w3docs.com/learn-html/html-blink-tag.html
-
Thanks, works great!