-
Content Count
3018 -
Joined
-
Last visited
-
Days Won
108
Everything posted by dummzeuch
-
Actually it's much easier to get money from management for an update whenever it is being released than skipping a few versions and then argue that a particular release is so important that you must buy it. It's even easier with a subscription because then you don't have to argue at all, once you got the subscription. This gets worse with company size. Of course that particular reason might not be valid for you or your company.
-
Which version of GExperts and which version of Delphi are we talking about? (Did you create a bug report?)
-
I agree, mostly, at least when it comes to upgrading from 10.2 to 10.3. The disadvantages of the unstable IDE offset the advantages of new language and IDE features by far. But I would have upgraded from 2007 to any XE version (up to 10.2) if it weren't for the subtle bugs the Unicode transition is likely to bring to code that isn't prepared for it (we still have code that uses strings as buffers for binary data, even though I have cleaned it up a lot). There are of course no unit tests for this legacy code, and on top of that they are difficult to write, because they usually rely on some hardware to communicate with. And just to add more fun, this code must run on Windows XP, which is no longer officially supported by the RTL and even less by the IDE (did anybody try to install recent Delphi versions on XP? I would be interested in your findings). That is a major stumbling block(?) right now.
-
It's a hack (there is no OTA access to the debugger in Delphi 2005 to 2007): The plugin reads the output memo from the dialog and then tries to convert it. It then directly writes the result to the memo. That has some drawbacks of course: long text is truncated so the conversion won't be complete. Float strings do not have the full precision, so converting them to TDateTime is also restricted in the precision, mostly on the time part. Yes, I decided that apparently nobody is interested, so I simply kept it to myself. If anybody wants it, I'll make the source code available (if I can still find it).
-
Just in case somebody needs TStringList and TDateTime visualizers for Delphi 2005, 2006 or 2007: here you go
-
Actually when I did some performance comparisons between Delphi 2007 and 10.2 with the same code and the same compiler settings, I got some noticeable improvements (yes I did timings). That's one particular program though and it is doing heavy graphics manipulation with mostly integer arithmetics, but still, it's evidence that the compiler was indeed improved since 2007. I can't say anything about improvements over the last few releases though. And the IDE is definitely eating more CPU in every new release.
-
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Good point, I added the manual test later to make THashedStringList work with the same code as a sorted TStringList. It shouldn't hurt performance though since the expensive search code is executed anyway to find the place for inserting the new string. btw: I appreciate your feedback on the testing code, even if it might not have sounded like I did. -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Obviously, as you pointed out yourself, I am adding duplicates, which the string list should ignore. (That actually is based on my "real world" usage of the list which I want to replace.) I know of no way to achieve that otherwise, or is there one that I don't know about? -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
You are right about that this is not a good test. My goal was not to create a real performance test for it, just something easy to write that gives me an idea which possible solution to investigate further. But yes, inserting strings in ascending order is definitely going to create some bias. Where am I sorting the string list? It's set to be sorted in the beginning and not changed. Actually I didn't post the code for the string list at all, just for the hash and the dictionary. (OK, i did) -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Hey, I just noted that my dzlib is missing from that list. đ Thanks for the hints. -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Hm, I must be doing something wrong. I can't see any improvement of a TStringHash over a sorted TStringList. Adding the same entries to a TStringHash took 3.12 seconds while it took 3.07 for a sorted TStringList. The same took 0.32 seconds for a TDictionary. Looking them up with ValueOf took approximately the same amount of time for TStringHash and sorted TStringList, while for TDictionary it took 0.32 seconds. I tried sizes of 1024 and 10240. This is the timing code: procedure TForm1.DoTiming(sl: TStringHash); const CYCLES = 100; var IdxCycles: Integer; Idx1: Integer; Idx2: Integer; Idx3: Integer; sw: TStopwatch; s: string; Idx: Integer; begin sw := TStopwatch.StartNew; for IdxCycles := 1 to CYCLES do begin for Idx1 := Ord('A') to Ord('Z') do begin for Idx2 := Ord('A') to Ord('Z') do begin for Idx3 := Ord('A') to Ord('Z') do begin s := chr(Idx1) + chr(Idx2) + chr(Idx3); if sl.ValueOf(s) = -1 then sl.Add(s, Idx1 * 10000 + Idx2 * 100 + Idx3); end; end; end; end; sw.Stop; m_Output.Lines.Add('Add: ' + sw.Elapsed.ToString); sw.Reset; sw.Start; for IdxCycles := 1 to CYCLES do begin for Idx1 := Ord('A') to Ord('Z') do begin for Idx2 := Ord('A') to Ord('Z') do begin for Idx3 := Ord('A') to Ord('Z') do begin s := chr(Idx1) + chr(Idx2) + chr(Idx3); Idx := sl.ValueOf(s); Assert(Idx = Idx1 * 10000 + Idx2 * 100 + Idx3); end; end; end; end; m_Output.Lines.Add('IndexOf: ' + sw.Elapsed.ToString); end; The code for TStringList is very similar. It uses AddObject instead of Add and IndexOf instead of ValueOf. procedure Tf_HashedStringListTest.DoTiming(sl: TStringList); const CYCLES = 100; var IdxCycles: Integer; Idx1: Integer; Idx2: Integer; Idx3: Integer; sw: TStopwatch; s: string; Idx: Integer; begin sl.Sorted := True; sl.CaseSensitive := True; sl.Duplicates := dupError; sw := TStopwatch.StartNew; sl.BeginUpdate; for IdxCycles := 1 to CYCLES do begin for Idx1 := Ord('A') to Ord('Z') do begin for Idx2 := Ord('A') to Ord('Z') do begin for Idx3 := Ord('A') to Ord('Z') do begin s := chr(Idx1) + chr(Idx2) + chr(Idx3); if sl.IndexOf(s) = -1 then sl.AddObject(s, Pointer(Idx1 * 10000 + Idx2 * 100 + Idx3)); end; end; end; end; sl.EndUpdate; sw.Stop; m_Output.Lines.Add(sl.Count.ToString + ': Add: ' + sw.Elapsed.ToString); sw.Reset; sw.Start; for IdxCycles := 1 to CYCLES do begin for Idx1 := Ord('A') to Ord('Z') do begin for Idx2 := Ord('A') to Ord('Z') do begin for Idx3 := Ord('A') to Ord('Z') do begin s := chr(Idx1) + chr(Idx2) + chr(Idx3); sl.IndexOf(s); end; end; end; end; m_Output.Lines.Add(sl.Count.ToString + ': IndexOf: ' + sw.Elapsed.ToString); And the one for the TDictionary just calls TryGetValue instead of IndexOf and Add instead of AddObject. I guess it has something to do with the limited length of the strings. Or I am overlooking something else entirely (it has been a long day and I'm not going to test the other solutions right now). -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Would you please be so kind and send it to me via private message? (Unless of course you prefer to attach it publicly to this thread.) -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Both look interesting, thanks. Now, I just need to find the time to run timing tests. đ -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
If I remember correctly (I bought Tomes of Delphi years ago), the source is not freely available. But it's a good idea, I'll have to check. -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Yes: I thought of improving it too, but it probably would be more work than writing my own. Just the fact that it's based on TStrings adds overhead that I would like to avoid. (I guess you meant THashedStringlist, because if I remember correctly, TStringHash isn't even exported.) -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
What's the license of this code? -
pre-generic dictionary class
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Even if that was as easy as it sounds, I doubt that this meets the definition of "free implementation". Yes, this is what many people tell me. I might even drop some of them, but since I do most of my professional work with Delphi 2007 (the last pre Unicode version), dropping support for it in GExperts would not really be smart. -
Interesting size reduction algorithm for HashTable
dummzeuch replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
You must keep in mind that Embarcadero only occasionally syncs the public jira with their internal one. Usually just before a new release lots of entries get closed. Unfortunately that does not always mean that they have been fixed. -
Delphi is 25 years old - my life story with Delphi
dummzeuch posted a topic in Tips / Blogs / Tutorials / Videos
Everybody seems to be blogging about Delphi having been around for 25 years, so I wonât stay back and tell some of my story. When I finished university and started a job, Delphi was just about being âbornâ and I was working with Turbo Pascal and later Visual Basic. VB was great in some aspects because it allowed to easily design user interfaces and write code only where you needed it. It wasnât after several years later that I was introduced to Delphi when I took a job at fPrint UK Ltd. (Yes, thatâs what web pages looked in 1997) and moved from Germany to the UK. The time I worked there was among the best of my life. I had some great coworkers there who were expert software developers ... read on in the blog post. -
Delphi is 25 years old - my life story with Delphi
dummzeuch replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Which web page are you talking about? Mine? fPrint's? If it's the latter: I think it originally had a background color matching the GIFs' background, so it didn't look quite as bad as in the archived version. -
Exception in constructor of class taking ownership of an object instance
dummzeuch posted a topic in Algorithms, Data Structures and Class Design
Given a class like this: type TMyClass = class private FSomeInstance: TSomeOtherClass; public constructor Create(_SomeInstance: TSomeOtherClass); destructor Destroy; override; end; [...] constructor TMyClass.Create(_SomeInstance: TSomeOtherClass); begin inherited Create; FSomeInstance := _SomeInstance; // other code here end; destructor TMyClass.Destroy; begin FSomeInstance.Free; inherited; end; Note: The class takes ownership of the TSomeOtherClass instance passed to it in the constructor. It frees it in its destructor. How would you write the code constructing it? My current code looks like this: SomeInstance := TSomeOtherClass.Create; try MyInstance := TMyClass.Create(SomeInstance); SomeInstance := nil; finally FreeAndNil(SomeInstance) end; The try..finally is there for handling the case where TMyClass.Create raises an exception, so there won't be a memory leak. But unfortunately the destructor is called even for partially created instances, so if the code after assigning FSomeInstance raises an exception, the instance of TSomeOtherClass would be freed twice. The only safe way I can think of would be to change TMyClass.Create as follows: constructor TMyClass.Create(var _SomeInstance: TSomeOtherClass); begin inherited Create; FSomeInstance := _SomeInstance; _SomeInstance := nil; // other code here end; If an exception gets raised in the inherited constructor (or in any other code before setting FSomeInstance) FSomeInstance would be nil, and _SomeInstance would be freed in the calling code. If it happens after setting _SomeInstance to nil, the destructor would free FSomeInstance and the calling code would not, becuse the var parameter was set to nil, which FreeAndNil (or even .Free) would detect. Of course, I could use Interfaces and rely on reference counting. -
Exception in constructor of class taking ownership of an object instance
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
I was assuming that this constructor should replace the one in my original example, where it was called from within a try finally block: constructor TMyClass.Create(_SomeInstance: TSomeOtherClass); begin inherited Create; // other code here FSomeInstance := _SomeInstance; end; If that's not the case, you have a memory leak if the inherited Create fails. -
The TTimer component has a minimum interval of 50ms. I understand that this is a limitation of the Windows timer which uses messages. What would be the alternative if I need smaller intervals, e.g. down to 10ms? The code is still supposed to be run in the main VCL thread. It doesn't matter if some events get lost because executing the code takes longer than the timer interval because the computer is busy. I just want to be able to get a smaller interval if the computer can support it.
-
Exception in constructor of class taking ownership of an object instance
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
As Dalija said: Raising exceptions in the constructor is possible and even normal (e.g. TFileStream.Create for a file that does not exist or maybe is only temporarily not available). It's documented that the destructor must handle partly constructed objects. Allen Bauer blogged about this in 2006 (aparently he has removed his About Me page from the blog, or did it never have one?) But yes, many Delphi developers are not aware of this. I only recently (as in "a few years, maybe a decade ago") became aware of this issue and am still finding code that does not take this into account. -
Dictionaries, Hashing and Performance
dummzeuch replied to Clément's topic in Algorithms, Data Structures and Class Design
That Wikipedia article links to an article by Thomas Wang Prime Double Hash Table from 1997 which explains what the point of choosing a prime number is. That sounds plausible to me, unless of course it is outdated by now due to different implementations of hash tables and hash functions.- 59 replies
-
- tdictionary
- tstringlist
-
(and 2 more)
Tagged with: