-
Content Count
2976 -
Joined
-
Last visited
-
Days Won
106
Everything posted by dummzeuch
-
Depth First Search vs. Breadth First Search in directories
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
My tests show no performance difference at all between DFS und BFS using FindFirst/FindNext. Both take nearly exactly 60 seconds on my test machine traversing the same directory tree on a Samba server. Trying to use TDirectory did not result in any improvement. It takes about twice as long. DFS code: var DirsWithJpg: TArray<string>; procedure CheckDirectory(const _Dir: string); var DirBs: string; sr: TSearchRec; ContainsFiles: boolean; ContainsSubdirs: boolean; begin ContainsFiles := False; ContainsSubdirs := False; DirBs := IncludeTrailingPathDelimiter(_Dir); if FindFirst(DirBs + '*.*', faAnyFile, sr) = 0 then begin try repeat if (sr.Name = '.') or (sr.Name = '..') then begin // ignore end else if (sr.Attr and faDirectory) <> 0 then begin // directory ContainsSubdirs := true; // recursive Depth First Search CheckDirectory(DirBs + sr.Name); end else if sr.Attr and (faHidden or faSysFile or faSymLink) = 0 then begin // regular file if not ContainsFiles then begin if SameText(ExtractFileExt(sr.Name), '.jpg') then begin ContainsFiles := true; end; end; end else begin // ignore special files end; until FindNext(sr) <> 0; finally FindClose(sr); end; end; if ContainsFiles then begin if ContainsSubdirs then begin m_Result.Lines.Add(Format('Directory %s contains files and subdirectories, ignoring it.', [_Dir])); end else begin DirsWithJpg := DirsWithJpg + [_Dir]; end; end; end; var Stopwatch: TStopwatch; begin Stopwatch.Reset; Stopwatch.Start; CheckDirectory('\\server\share\dir'); Stopwatch.Stop; m_Result.Lines.Add(Format('FindFirst/Next DBF: Found %d dirs in %.3f seconds', [Length(DirsWithJpg), Stopwatch.Elapsed.TotalSeconds])); end; BFS code: var DirsWithJpg: TArray<string>; DirsToSearch: TStringList; procedure CheckDirectory(const _Dir: string); var DirBs: string; sr: TSearchRec; ContainsFiles: boolean; ContainsSubdirs: boolean; begin ContainsFiles := False; ContainsSubdirs := False; DirBs := IncludeTrailingPathDelimiter(_Dir); if FindFirst(DirBs + '*.*', faAnyFile, sr) = 0 then begin try repeat if (sr.Name = '.') or (sr.Name = '..') then begin // ignore end else if (sr.Attr and faDirectory) <> 0 then begin // directory ContainsSubdirs := true; // add to list for later processing DirsToSearch.Add(DirBs + sr.Name); end else if sr.Attr and (faHidden or faSysFile or faSymLink) = 0 then begin // regular file if not ContainsFiles then begin if SameText(ExtractFileExt(sr.Name), '.jpg') then begin ContainsFiles := true; end; end; end else begin // ignore special files end; until FindNext(sr) <> 0; finally FindClose(sr); end; end; if ContainsFiles then begin if ContainsSubdirs then begin m_Result.Lines.Add(Format('Directory %s contains files and subdirectories, ignoring it.', [_Dir])); end else begin DirsWithJpg := DirsWithJpg + [_Dir]; end; end; end; var Stopwatch: TStopwatch; begin Stopwatch.Reset; Stopwatch.Start; DirsToSearch := TStringList.Create; try DirsToSearch.Add('\\server\share\dir'); while DirsToSearch.count > 0 do begin CheckDirectory(DirsToSearch[0]); DirsToSearch.Delete(0); end; finally FreeAndNil(DirsToSearch); end; Stopwatch.Stop; m_Result.Lines.Add(Format('FindFirst/Next BFS: Found %d dirs in %.3f seconds', [Length(DirsWithJpg), Stopwatch.Elapsed.TotalSeconds])); end; The naive approach using TDirectory takes about twice as long because of the calls to .GetFiles and .GetDirectories each call FindFirst/FindNext per directory. (It also finds 2 less directories containing jpg files, so there is probably a bug somewhere, but I didn't investigate this any further.) var DirsWithJpg: TArray<string>; procedure CheckDirectory(const _Dir: string); var Files: TArray<string>; Dirs: TArray<string>; i: Integer; begin Files := TDirectory.GetFiles(_Dir, '*.jpg'); Dirs := TDirectory.GetDirectories(_Dir); if Length(Files) > 0 then begin if Length(Dirs) > 0 then begin m_Result.Lines.Add(Format('Directory %s contains files and subdirectories, ignoring it.', [_Dir])); end else DirsWithJpg := DirsWithJpg + [_Dir]; end else begin for i := Low(Dirs) to High(Dirs) do CheckDirectory(Dirs[i]); end; end; var Stopwatch: TStopwatch; begin Stopwatch.Reset; Stopwatch.Start; CheckDirectory('\\server\share\dir'); Stopwatch.Stop; m_Result.Lines.Add(Format('DirGetFiles: Found %d dirs in %.3f seconds', [Length(DirsWithJpg), Stopwatch.Elapsed.TotalSeconds])); end; I thought about using TDirectory.FileSystemEntries instead but could not think of a simple way to implement this. It's probably possible using a Predicate but that's not really any simpler than directly using FindFirst/FindNext. There is probably still some space for improvements and the code is not really clean, e.g. accessing variables of the outer procedure. So, now I'll have a look at calling Windows.FindFirstFileEx instead of FindFirst, but I don't have much hope that this will help much. -
Yes, I'm sure it could.
-
Ouch! Forget it: I didn't reset the stopwatch first: var Stopwatch: TStopwatch; begin Stopwatch.Reset; //<<<--- this was missing Stopwatch.Start; sleep(3000); Stopwatch.Stop; m_Result.Lines.Add(format('Took %.3f seconds', [Stopwatch.Elapsed.TotalSeconds])); end;
-
On the other hand, if I only want to create one installer, it's easier to temporarily edit the makeinstallers.cmd, where I can simply copy one existing line rather than having to remember exactly which parameters I'd have to pass: rem [...] rem *** copy one line from the list below here *** rem *** and remove two REMs *** rem call :makeinst RS103 RS10.3 rem pause rem goto :eof :list call :makeinst Delphi6 D6 call :makeinst Delphi7 D7 call :makeinst Delphi2005 call :makeinst BDS2006 call :makeinst Delphi2007 call :makeinst RS2009 call :makeinst RS2010 call :makeinst RSXE1 call :makeinst RSXE2 call :makeinst RSXE3 call :makeinst RSXE4 call :makeinst RSXE5 call :makeinst RSXE6 call :makeinst RSXE7 call :makeinst RSXE8 call :makeinst RS100 RS10 call :makeinst RS101 RS10.1 call :makeinst RS102 RS10.2 call :makeinst RS103 RS10.3 call :makeinst RS104 RS10.4 rem [...]
-
Depth First Search vs. Breadth First Search in directories
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
That might for a change actually be an option, as the program in question is developed with Delphi 10.2 rather than my usual work horse Delphi 2007. I'm not yet used to those "new" utility units. I just had a look at the sources. As @Vandrovnik already said: It internally also uses FindFirst / FindNext in the same way my program did, so I don't expect any improvements. WalkThroughDirectory also recursively does a depth first search. In addition it calls two different callbacks, which won't improve performance either. I'll now try to use FindFirstEx and also implemtent BFS and do some timing on each. -
Thanks, I missed that one. As for the others I now know why I didn't see those errors: I compiled these projects with Delphi 2007 only. Maybe I should switch to a more modern version.
-
all should be fixed now in svn
-
This works fine for me without the change and regardless whether I do a command line build (__build_Project.cmd) or use the IDE. The GXpertsRS103 project contain the ..\..\ExternalSource directory in the search path for "All configurations - All platforms", so the change should not be necessary. Or was this for one of the stand alone projects too?
-
10.4 move editor tabs around not working
dummzeuch replied to Erix A.'s topic in Delphi IDE and APIs
Works for me, but is a bit sluggish. -
In my installation nothing has changed in this respect. The project window can be pinned and unpinned, where "unpinned" means it's just a small panel to the right that makes the window visible when clicking on it. Maybe undocking and docking it again will solve the problem?
-
If you want to use the"stand alone" tools in GExperts, you might find that they don't work if the bpl files it needs are not in the search path. These tools call the dll, the dll is an IDE plugin, an IDE plugin needs some bpls, so there is no way around that (other than making those tools not use the dll).
-
Depth First Search vs. Breadth First Search in directories
dummzeuch replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
That might for a change actually be an option, as the program in question is developed with Delphi 10.2 rather than my usual work horse Delphi 2007. I'm not yet used to those "new" utility units. Thanks for the pointer. -
Thanks for the hints. I haven't checked this stand alone tools for some time. I'm surprised about the change to gx_dbugintf. I'll need to have a closer look. Also thanks for the changed prebuild.cmd
-
bug #192 Message Dialog Expert form is too small in Delphi 10.4
-
https://blog.dummzeuch.de/2018/08/18/gnugettext-support-for-the-gexperts-message-dialog-expert/ You can also turn it off, there is a checkbox for it in the dialog.
-
No, you will get new licenses for all included Delphi versions and in the case of the named user licenses for each user. The old licenses will continue to work for a while and then Embarcadero will invalidate them. I also got a link for a special web page that lists downloads for all my included Delphi versions. I don't remember if I had to ask for it or got it automatically. Unfortunately, the notification email I get when a new Delphi release is available always contained a wrong download link and I keep forgetting about the special page I mentioned above. But support was always helpful in that case.
-
So, does that mean we have a Delphi 10.4 release?
-
For what it's worth: We hired a new Delphi developer about 4 years ago (because the one we hired 10 years ago left). And we are constantly creating new and improving old programs that are used internally, and some that are used in our parent company and sold to costumers who buy our custom built measurement vehicles or data. We recently started a new tool that required Delphi 10.2 features and even bought two new licenses for that. And I'm waiting for Delphi 10.4 in the hope that one particular bug in the IDE has been fixed that prevented another new tool to move forward. But we might be an exception, because I'm a fan of Delphi and I'm making most of the decisions regarding the development environment. Maybe my successor will decide to drop all that "legacy" stuff and start rewriting everything with "modern" technology. If he is lucky, the company might even survive such a move, barely, and with a software department of 10 instead of 3 people. But hey, that would create 7 new jobs.
-
The answer is equally simple: Once it has been activated, No.
-
The easiest way to protect against ELC server failures, is running it in a VM and keeping a working backup of that machine. We use a XenServer VM and run ELC under a minimal Ubuntu server, so the backups aren't that large.
-
Depends who you ask. I have the impression that the terms of these licenses and what kind of restrictions they impose is not that widely known in the company. But I might be wrong. I don't remember reading about a restriction of 3 installations (but I may have overlooked it) and since there is no way to see the number of (passive) installations in ELC and also no way to unregister an installation I don't see how they could enforce it. Of course they could update the ELC software to enforce it and have new Delphi versions require the update. Maybe that's not 3 installations in total but 3 active installations, that is "the IDE is running" at the same time? For me even only 3 installations would have been better than being stuck with a debugging problem on a Friday with no way to install Delphi on the computer in question, because a "bump" was not possible until Monday (or at all). I think we currently have about 20 Delphi 2007 installations, most of them are only used once or twice a year, some not even once a year. But when I need them, it's usually in a hurry. But not all these installations are Network Named User licenses, we had quite a few ordinary licenses before, that were either from an upgrade or came for free with later Delphi versions. These were never converted.
-
Neither does Borland or Codegear.
-
You are right: ELC only covers Delphi 2007 and later. Delphi 6 and 7 did not need activation, that was optional. I'm not sure about Delphi 2005 and 2006 though.
-
While you have a valid subscription, convert your license to a "Network named user license" and install the Embarcadero License Center (server under e.g. Ubuntu on a virtual machine). Then you can have as many installations on your LAN as you want and even use several at the same time (there is a limit, but I haven't hit it yet). And you will never again need a "bump" either.
-
Tools Api: how to detect a key has been pressed in the editor window?
dummzeuch replied to santiago's topic in Delphi IDE and APIs
Just to make that clear: The url Dave posted is for browsing the source code in a web browser, not for downloading it with subversion. The url for subversion is this: https://svn.code.sf.net/p/gexperts/code/trunk