dzPackageInst 1.0.2 for Delphi 6 to 10.3 released

 Delphi  Comments Off on dzPackageInst 1.0.2 for Delphi 6 to 10.3 released
Feb 282020
 

Today I released version 1.0.2 of dzPackageInst. Its a command line tool that allows installing and uninstalling design time packages into the Delphi 6 to 1.3 IDEs.

Source code and download are available from the project page on SourceForge.

It’s also part of my buildtools which I use for nearly all my projects.

 Posted by on 2020-02-28 at 09:37

If the hosts file on Windows XP does not work

 Windows, Windows XP  Comments Off on If the hosts file on Windows XP does not work
Feb 172020
 

I just had one of these dreaded occurrences where the hosts file did not work on a Windows XP installation. (Yes, you read that correctly: “Windows XP”. I still have got a few installations of that to maintain.)

I could not figure out what the problem was, so I turned to Google which found “hosts file ignored, how to troubleshoot?” on ServerFault. The accepted answer lists several steps to trouble shoot. The one that helped me was:

5. Permissions
Sometimes there are issues with permissions on the file, the file
attributes, and similar things. To recreate the file with default
permissions:

    1. Create a new text file on your desktop.
    2. Copy and paste the contents of your current hosts file into
       this file in Notepad.
    3. Save the new text file and rename it to hosts.
    4. Copy (do not move) the file to your
       %SystemRoot%\System32\drivers\etc
       directory, and overwrite the old file.

Last point is important: Copying works, moving doesn't.

Unfortunately the described steps did not work for me because I already had moved the hosts file from the desktop to c:\Windows\System32\drivers\etc so the original file and its permissions was already overwritten. What I did to solve this was:

  1. Follow the steps 1 to 3 above.
  2. Delete the original hosts file in the %SystemRoot%\System32\drivers\etc directory
  3. Copy one of the other files in that folder (I used “services”) and rename the copy to “hosts”
  4. Follow step 4 above

Now ping works as expected and connecting to the Embarcadero License Server also does.

 Posted by on 2020-02-17 at 16:29

TStringList vs. THashedStringList vs. TDictionary

 Delphi  Comments Off on TStringList vs. THashedStringList vs. TDictionary
Feb 162020
 

Prompted by the topic Dictionaries, Hashing and Performance in the international Delphi Praxis forum I did some timing to compare the performance of data structures in the Delphi runtime library that can be used to store data indexed by strings:

  • a sorted, case sensitive TStringList (available since Delphi 6)
  • a sorted, case sensitive THashedStringList (available since Delphi 6)
  • a TDictionary<string,Integer> (available since a Delphi 2009)

Just in case you did not know about THashedStringList: It is a TStringList descendant declared in System.IniFiles. It’s used to speed up access to TMemIniFile. (EDIT: As Uwe Raabe pointet out, that’s no longer true. As of Delphi 10.3 (and possibly earlier, I haven’t checked) TMemIniFile also uses TDictionary<string,Integer>.)

The test adds 676 strings (‘AA’ .. ‘ZZ’) to each structure and does that 10000 times (which means that there are quite a few checks for duplicates to be done on adding). Then – again 10000 times – it does a lookup for each of these strings.

Of course that is just a simple test and it is neither a large number of entries nor long strings. I just wanted to get a feel for the performance of these structures.

Here is the main code for TStringList and THashedStringList:

procedure Tf_HashedStringListTest.DoTiming(sl: TStringList);
const
  CYCLES = 10000;
var
  k: integer;
  i: integer;
  j: integer;
  sw: TStopwatch;
  s: string;
  Idx: Integer;
begin
  sl.Sorted := True;
  sl.CaseSensitive := True;
  sl.Duplicates := dupError;
  sw := TStopwatch.StartNew;
  sl.BeginUpdate;
  for k := 1 to CYCLES do begin
    for i := Ord('A') to Ord('Z') do begin
      for j := Ord('A') to Ord('Z') do begin
        s := chr(i) + chr(j);
        if not sl.Find(s, Idx) then
          sl.AddObject(s, Pointer(i * 100 + j));
      end;
    end;
  end;
  sl.EndUpdate;
  sw.Stop;
  m_Output.Lines.Add(sl.Count.ToString + ': Add: ' + sw.Elapsed.ToString);

  sw.Reset;
  sw.Start;
  for k := 1 to CYCLES do begin
    for i := Ord('A') to Ord('Z') do begin
      for j := Ord('A') to Ord('Z') do begin
        s := chr(i) + chr(j);
        sl.IndexOf(s);
      end;
    end;
  end;
  m_Output.Lines.Add(sl.Count.ToString + ': IndexOf: ' + sw.Elapsed.ToString);
end;

And very similar for TDictionary:

procedure Tf_HashedStringListTest.DoTiming(sl: TDictionary<string, integer>);
const
  CYCLES = 10000;
var
  k: integer;
  i: integer;
  j: integer;
  sw: TStopwatch;
  s: string;
  v: integer;
begin
  sw := TStopwatch.StartNew;
  for k := 1 to CYCLES do begin
    for i := Ord('A') to Ord('Z') do begin
      for j := Ord('A') to Ord('Z') do begin
        s := chr(i) + chr(j);
        if not sl.TryGetValue(s, v) then
          sl.Add(s, i * 100 + j);
      end;
    end;
  end;
  sw.Stop;
  m_Output.Lines.Add(sl.Count.ToString + ': Add: ' + sw.Elapsed.ToString);

  sw.Reset;
  sw.Start;
  for k := 1 to CYCLES do begin
    for i := Ord('A') to Ord('Z') do begin
      for j := Ord('A') to Ord('Z') do begin
        s := chr(i) + chr(j);
        sl.Items[s];
      end;
    end;
  end;
  m_Output.Lines.Add(sl.Count.ToString + ': IndexOf: ' + sw.Elapsed.ToString);
end;

The result is not really surprising:

TDictionary is the winner by a large margin, followed by THashedStringList and then TStringList. The two string lists only differ in the IndexOf times, the adding times are very similar.

On my computer, with an AMD Phenom II XE 1090T processor, and compiled with Delphi 10.3 I get the following times:

Structure Time for Add [sec] Time for IndexOf [sec]
TStringList 7.43 7.48
THashedStringList 7.45 4.40
TDictionary 1.05 1.04

EDIT: I just found that changing the code for the THashedStringlist from using Find to using IndexOf reduced the time for adding entries to about the same time as for IndexOf. So both are about 4 seconds. This makes me wonder whether there is a bug in THashedStringList because it does not override AddObject. It simply inherits it from TStringList which for sorted lists calls Find to see if the string is already in the list. In contrast to IndexOf the Find method does not use the hash so it’s as slow as in TStringList. But maybe that is on purpose because the hashes get calculated rather frequently for all entries. I get the impression that THashedStringList is not really well implemented and nobody noticed because it was just good enough.

EDIT2: As it was only used in TMemIniFile to get fast access to the entries without needing them to be sorted, the implementation probably was good enough. My test above doesn’t check the performance of Add for an unsorted THashedStringList which is what TMemIniFile used.

If you like, you can download the full source code of my test program.

 Posted by on 2020-02-16 at 16:05

Delphi is 25 years old

 Delphi  Comments Off on Delphi is 25 years old
Feb 152020
 

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 (Hello Mamta, Allan, Vitaly and Linden, if you read this. And RIP to you, Andrew). We were already using Delphi 3 by that time and it delivered everything that Visual Basic had only been promising. I was hooked for life. We also worked on Virtual Pascal, a Pascal compiler compatible to Borland Pascal and partly Delphi which had originally been Vitaly’s project. Working for fPrint later made me move to Paris (France) for a while. Back then I also made first contact with GExperts.

Fast forward to 2020. I had changed jobs frequently until 2007 due to companies I worked for being bought by others and working conditions deteriorating afterwards. I made my fist million D-Mark (and lost most of it shortly afterwards, never gaining it back). I even had to go back to programming in Visual Basic 6 for a while (and I hated it).

Today I work at TÜV Rheinland Schniering GmbH (formerly Schniering Ingenieurgesellschaft) and develop Software in Delphi for road condition surveys. It is running on our measurement vehicles and also used in the office and at customer’s sites. As software development jobs go this is way cool, and again I have some great coworkers, this time not only in software development, because we also build our own measurement hardware and even developed the elevator examination system Liftis© (software by me, hardware by my coworkers) for our parent company TÜV Rheinland.

I really wonder how my career and my life would have turned out if Delphi hadn’t been around at the time I started out. Maybe I would have ended up as a COBOL programmer for life at Debeka (which was my first employer). Or I would have written embedded software in C for some company I didn’t even get to know. At some time I even interviewed for a job at a company (I forgot the name, but it was located in Dreieich near Frankfurt, Germany) that was developing a search engine written in Delphi (Edit: I remembered: They called themselves “Twirlix” and apparently folded in 2001, shortly after my interview)

Thinking back, this has been some exciting time to be alive and for me Delphi played a significant part of it.

 Posted by on 2020-02-15 at 12:22