Mike Torrettinni
Members-
Content Count
1509 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Mike Torrettinni
-
Football Championship Group Stage Order
Mike Torrettinni replied to PawelPepe's topic in Algorithms, Data Structures and Class Design
I suggest showing code that you have here or attach files here (.pas not .zip). I doubt anybody will download a zip file from external source. -
Delphi 11.1 - a month later
Mike Torrettinni replied to Mike Torrettinni's topic in Delphi IDE and APIs
I lowered my expectations what they can/will deliver, so I think that's why I'm surprised of the D11.1 quality. So far, I'm not touching any High DPI stuff, yet. But I would probably get to the same conclusion as you, not mature enough yet. -
Football Championship Group Stage Order
Mike Torrettinni replied to PawelPepe's topic in Algorithms, Data Structures and Class Design
If you search this forum, you will see this kind of questions never get any answer here, but you will probably get a response within minutes if you post this as project on freelancer and set your minimum budget. -
Delphi 11.1 - a month later
Mike Torrettinni replied to Mike Torrettinni's topic in Delphi IDE and APIs
1 more observation: in 10.2, when ctrl+click worked, it worked even if code in other part of the project didn't compile. 11.1 needs compiler to not fail and ctrl+click works. Example: working on UnitA and try to compile and it fails.. perhaps a type is missing or used incorrectly. Open UnitB and check some info, use ctrl+click to jump around. In 10.2 the ctrl+click will work in UnitB. In 11.1 the Ctrl+click will not work anywhere, it stops working for the whole project, because the last compile failed. It starts working as soon as compile is successful. -
Simple debugger bug in 11.1
Mike Torrettinni replied to Mike Torrettinni's topic in Delphi IDE and APIs
OK, it makes sense. Well, at least the workaround is simple: don't give debugger any tough math to do. -
Simple debugger bug in 11.1
Mike Torrettinni replied to Mike Torrettinni's topic in Delphi IDE and APIs
Hm, quite disappointing, but maybe this is very rarely used the way I use MidStr, or perhaps MidStr is on the way to be deprecated and they don't want to waste time on it. -
Survey of Delphi Versions in use??
Mike Torrettinni replied to Ian Branch's topic in Community Management
If you decide to go ahead with the survey, try to give us more options, for example I use D2006 every few years for a few weeks. So, when I use it, I use it 75%-100% of the time, the rest is split between D10.2 and now D11. D11 is the only one that I compile for 64bit, and Linux. Perhaps you can frame the purpose of the survey, like if you are you planning to develop something and sell to Delphi developers, in that case I would select D11 as the only version I would be interested in any new component/tool to use with. -
It seems very likely this is the case. You would think David would remember all past projects acquired by bigger companies with promises of 'gold' and in reality they got used for marketing, then pushed aside and lost in space, in very short time.
-
HCView - an open source BSD-licensed Rich Edit Control in Delphi
Mike Torrettinni replied to Edwin Yip's topic in Delphi Third-Party
Did you try this component? I would be interested if it has faster implementation of search and highlight - faster than current TRichEdit. -
HCView - an open source BSD-licensed Rich Edit Control in Delphi
Mike Torrettinni replied to Edwin Yip's topic in Delphi Third-Party
OK, fixed too 🙂 -
HCView - an open source BSD-licensed Rich Edit Control in Delphi
Mike Torrettinni replied to Edwin Yip's topic in Delphi Third-Party
The link has some facebook details... if you wanna remove it. -
Can undefined function result point to valid/used data in memory?
Mike Torrettinni posted a topic in RTL and Delphi Object Pascal
It's quite common to initialize Result of string function with SetLength(Result, len) and then work with the Result, like: // Switch Upper to lower and lower to Upper case function SwitchCase(const aStr: string): string; var i: integer; begin SetLength(Result, Length(aStr)); // without Result := ''; for i := 1 to aStr.Length do if CharInSet(aStr[i], ['a'..'z']) then Result[i] := UpCase(aStr[i]) else Result[i] := LoCase(aStr[i]); end; And looking at debugger: the Result holds some data, which is overwritten with the code after SetLength. Of course if we initialize Result := ''; before SetLength, then Result is a new string. Before Result is initialized with SetLength, it is undefined, so it points to a random memory location, I guess. Is that always unused memory location or is there a danger that we are actually overwriting valid memory block (part of other string, or long array.,..) and can cause issues in the running code? -
Can undefined function result point to valid/used data in memory?
Mike Torrettinni replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
Thank you, very clear example. I was trying to see if compiler will make mistake or get confused if I put a 'surprise!' in there, like: procedure Main2; var s,s2: string; begin s := Test; s := Test; s2 := s; s2 := Test; Writeln('s = ' + s); Writeln('s2 = ' + s2); end; but still works as expected: -
Can undefined function result point to valid/used data in memory?
Mike Torrettinni replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
Thanks, I did read the link, but didn't get to the same conclusion as you describe it: I think I understand a bit better now, the difference of compiler initialization and our initialization of vars in the function. Is my understanding correct, if I say it like this (in non-expert language): the 'the compiler initializes' is not the same as we initialize local vars with localtIntVar := 0; or Result:= '';. The compiler initializes variables (including Result) (like assigns registers or memory pointers, or whatever, to each var) and we initialize the value of these variables. Strings local vars are managed, so compiler initializes variable and the value to ''. Integer local vars are not manage, so compiler only initializes variables and we need to initialize the value to 0 or whatever we need, manually. And in case of function Result, the initialization doesn't really just point to a random/undefined memory space, but it might keep a list of previously ready-to-be-reused hidden variables or it uses some other location, but never actual valid data. (as Frost pointed out this would be fundamental flaw if it changed the valid data) Right? -
I only use Indy for software update check, so very minimal. And I was looking into Indy status the other day and it seems pretty active, with recent bug fixes: https://github.com/IndySockets/Indy/issues?q=is%3Aissue+is%3Aclosed Didn't know about any new features implemented, but recent bug fixes are definitely a sign this is an active project. But I guess if I needed TLS 1.3 support, would probably be more worried about when and if it will be available.
-
Micro optimization: IN vs OR vs CASE
Mike Torrettinni posted a topic in Algorithms, Data Structures and Class Design
I have a few functions where I check if 'data' is 'a control', and in some cases I use MatchStr where I have string info, and IN where I have integer ID: function IsControlGroupA(const aControl: string): boolean; Result := MatchStr(aControl, ['Edit', 'Check', 'ComboBox', 'RadioBtn', 'ListBox']); end; function IsControlGroupX(aControl: integer): boolean; Result := aControl in [xConttrols.EditID, xConttrols.CheckID, xConttrols.ComboBoxID, xConttrols.RadioBtnID, xConttrols.ListBoxID]; end; Replacing MatchStr with OR is of course much faster - because we know MatchStr is quite inefficient compared to simple = comparison, so this is much faster: function IsControlGroupA(const aControl: string): boolean; Result := (aControl = 'Edit') or (aControl = 'Check') or (aControl = 'ComboBox') or (aControl = 'RadioBtn') or (aControl = 'ListBox'); end; Then I looked at IN and it looks like simple check of integers, which is fast anyway. So, I benchmarked if it's worth replacing it also with OR: function IsControlGroupX(aControl: integer): boolean; Result := (aControl = xConttrols.EditID) or (aControl = xConttrols.CheckID) or (aControl = xConttrols.ComboBoxID) or (aControl = xConttrols.RadioBtnID) or (aControl = xConttrols.ListBoxID); end; Then I remember reading Marco's response on Case vs If Else about a single comparison and jump: https://twitter.com/marcocantu/status/1501844578898530308?cxt=HHwWiMC-kf_rz9cpAAAA so I put Case into benchmarking and seems like Case is not suitable for my data, since I don't use a large number of ordinals, like Marco explained when Case is faster, and I don't use If Else, so probably not good case anyway, but I put it in so I know how it go against OR. In test benchmark, the OR is a winner, and Case is a bit slower especially in 64bit - which I'm slowly moving into anyway: I benchmarked with my current D 10.2.3 and D 11.1 running in VM: As Marco said, perhaps if I had a large number of checks and if I compared it to If Else, it could win. The real-life difference in one data sample, the most used check for a group is 6x faster using OR vs IN: using IN: using OR: So, definitely quite useful improvement! 1 fact about Case: as we know you can't use Case on non-constant expressions, so using Case for my functions would require a good amount of code change. If it proved to be significantly faster then OR, I would make the change, but it's not. As usual I'm just looking for comment on my observations, perhaps suggestion on something I don't see or didn't take into consideration. And the benchmark code - with the usual limitation of simple repeated calls: program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Diagnostics; type TControlsRec = record EditID, ButtonID, CheckID, FormID, FrameID, ListBoxID, PageControlID, TabControlID, RadioBtnID, ComboBoxID: integer; EditStr, ButtonStr, CheckStr, FormStr, FrameStr, ListBoxStr, PageControlStr, TabControlStr, RadioBtnStr, ComboBoxStr: string; end; var xControlsRec: TControlsRec; procedure AssignControlsRec; begin xControlsRec.EditID := 1; xControlsRec.EditStr := 'Edit'; xControlsRec.ButtonID := 2; xControlsRec.ButtonStr := 'Button'; xControlsRec.CheckID := 3; xControlsRec.CheckStr := 'Check'; xControlsRec.FormID := 4; xControlsRec.FormStr := 'Form'; xControlsRec.FrameID := 5; xControlsRec.FrameStr := 'Frame'; xControlsRec.ListBoxID := 6; xControlsRec.ListBoxStr := 'ListBox'; xControlsRec.PageControlID := 7; xControlsRec.PageControlStr := 'PageControl'; xControlsRec.TabControlID := 8; xControlsRec.TabControlStr := 'TabControl'; xControlsRec.RadioBtnID := 9; xControlsRec.RadioBtnStr := 'RadioBtn'; xControlsRec.ComboBoxID := 10; xControlsRec.ComboBoxStr := 'ComboBox'; end; function IsIN(aID: integer): boolean; begin Result := aID in [xControlsRec.ButtonID, xControlsRec.FormID, xControlsRec.ListBoxID, xControlsRec.TabControlID, xControlsRec.ComboBoxID]; end; function IsOR(aID: integer): boolean; begin Result := (aID = xControlsRec.ButtonID) or (aID = xControlsRec.FormID) or (aID = xControlsRec.ListBoxID) or (aID = xControlsRec.TabControlID) or (aID = xControlsRec.ComboBoxID); end; function IsCase(aID: integer): boolean; begin case aID of 2,4,6,8,10: Result := True; else Result := false; end; end; function IsCase2(aID: integer): boolean; begin case aID of 2: Result := True; 4: Result := True; 6: Result := True; 8: Result := True; 10: Result := True; else Result := false; end; end; const cLoop = 100000000; // Values/ControlIDs to search for // 3 values are in the group, 2 are not - similar ratio as in real data cSearch: array[1..5] of integer = (2,4,5,8,11); var vSW: TStopwatch; vBool:boolean; i: integer; begin AssignControlsRec; // IsIN vSW := TStopwatch.StartNew; for i := 1 to cLoop do begin vBool := IsIN(cSearch[1]); vBool := IsIN(cSearch[2]); vBool := IsIN(cSearch[3]); vBool := IsIN(cSearch[4]); vBool := IsIN(cSearch[5]); end; vSW.Stop; Writeln(Format('IsIN = %5s', [vSW.ElapsedMilliseconds.ToString])); // IsOR vSW := TStopwatch.StartNew; for i := 1 to cLoop do begin vBool := IsOR(cSearch[1]); vBool := IsOR(cSearch[2]); vBool := IsOR(cSearch[3]); vBool := IsOR(cSearch[4]); vBool := IsOR(cSearch[5]); end; vSW.Stop; Writeln(Format('IsOR = %5s', [vSW.ElapsedMilliseconds.ToString])); // IsCase vSW := TStopwatch.StartNew; for i := 1 to cLoop do begin vBool := IsCase(cSearch[1]); vBool := IsCase(cSearch[2]); vBool := IsCase(cSearch[3]); vBool := IsCase(cSearch[4]); vBool := IsCase(cSearch[5]); end; vSW.Stop; Writeln(Format('IsCase = %5s', [vSW.ElapsedMilliseconds.ToString])); // IsCase2 vSW := TStopwatch.StartNew; for i := 1 to cLoop do begin vBool := IsCase2(cSearch[1]); vBool := IsCase2(cSearch[2]); vBool := IsCase2(cSearch[3]); vBool := IsCase2(cSearch[4]); vBool := IsCase2(cSearch[5]); end; vSW.Stop; Writeln(Format('IsCase2 = %5s', [vSW.ElapsedMilliseconds.ToString])); readln; end. -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
@Pat Foley and @pmcgee thanks for the solution using a Set, but I can't really use them because the list of controls exceeds 256 items. But very good timings, will see if I can use the logic for some smaller pool of data. I have many that are definitely less than 100 count. -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
If it helps: when you add images they are listed below the post as Uploaded images and you can delete them by clicking on delete icon, if you can't delete them within the post: -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I pasted 2 profiler results in first post and you can see replacing IN with OR shaves off 0.5s. It's part of a search feature and verification of data type is significant portion of search runtime. -
That's interesting. From all the stuff that you can sue/get sued in US, also usually about the software the issue is late/non delivery, extra charges, quality... but, I've never heard of a case like this. Do you have any links about such case? What was the actual lawsuit about, what kind of the damage was caused? What country was that?
-
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Thanks and after trying to grasp the content of the links I realized I shouldn't be using micro optimization phrase at all! Will drop it from next topics, as I'm interested in whats faster but definitely I'm out of my comfort zone and not ready to dive into this topic the way it was expected because of the title. -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I knew there is a difference between them, more for strings - in one of my benchmarks using string typed consts resulted in faster runtime vs non-typed consts. But still don't know to what extent it affects every case that uses typed conts. Re-reading this thread, but still trying to process all the info there: -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Well, even with a real const in a record, I still get @SetElem: type TCtrls = record const ButtonID: integer = 2; FormID: integer = 4; ListBoxID: integer = 6; TabControlID: integer = 8; ComboBoxID: integer = 10; end; I tried with a var of TCtrls type, just in case if it makes a diff, still the same: var xCtrls: TCtrls; -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
OK, I think I see it now, const in a record vs const record. -
Micro optimization: IN vs OR vs CASE
Mike Torrettinni replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
OK, const record is not the same as const, wasn't aware of that - then how did you manage to get a integer const prefixed with xControlsRec, like xControlsRec.ButtonID? If I try a const with a dot in the name, it doesn't compile: const xCtrls.EditID: integer = 1; it complains: [dcc32 Error] Project1.dpr(93): E2029 '=' expected but '.' found If I set integer consts like this: const xButtonID: integer = 2; xFormID: integer = 4; xListBoxID: integer = 6; xTabControlID: integer = 8; xComboBoxID: integer = 10; the runtime is similar as before, still uses @SetElem: This is D10.2.3. When trying this in D11.1 in VM, it generates the same asm, so not sure how you got your completely different asm code: