Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by dummzeuch

  1. Hm, wasn't the point of the first post in this thread that FreeAndNil isn't big enough of a subject to make a whole video about? Two pages of discussion say otherwise.
  2. So does the check for <>nil in .Free
  3. I agree that it is a bug, but exactly because of this the issue can not be ignored.
  4. Actually, obj.Free already checks for NIL, so the if statement is unnecessary. FreeAndNil also does something different than the name implies: procedure FreeAndNil(var Obj); var temp: TObject; begin temp := TObject(Obj); TObject(Obj) := nil; Temp.Free; end; (That's the old, non-typesafe version, if I remember correctly) So it should actually be called NilAndFree because it first sets the Object reference to nil and only then calls its Free method. That has some implications if there is code in the destructor / called from the destructor that references the object instance via the same pointer (which shouldn't be done but I have seen it been done.
  5. The 13th (or even 14th in banks) monthly salary in Germany is no bonus, It is part of the regular salary and cannot be withheld if business is slow. It is usually paid with the November salary. It is kind of a tradition here. Personally I think that is kind of stupid. There isn't really any advantage in getting paid the yearly salary in 13 parts rather than 12, but apparently many people don't understand that and insist on it. Of course there are also contracts which specifically specify as a bonus (sometimes on top of the 13 monthly salaries), which in that case isn't considered a "13th monthly salary" but (guess what?) a bonus.
  6. Taking it to work and having it lying around on your desk for a while might actually help when the time comes to renegotiate your salary. On the other hand, I have had some first hand experience with COBOL and I am sure that 15000 (US$?) is not worth the pain. My memory of COBOL is even worse than Visual Basic (the original one, not VB.NET, I don't know the latter).
  7. One of my former coworkers started to call herself the Little Indian (she was of Indian descend and really tiny) after she heard one of the developers talking about little endian vs. big endian format. Somehow it didn't get old, we had a laugh every time she said that (the reason possibly was that we were drunk most of the time, playing Total Annihilation after office hours) Those were the days ...
  8. You are aware that you are talking about 10th of a percent, aren't you? I doubt that that is even statistically relevant.
  9. Hm, that's the median salary not the arithmetic average. Not sure what the effect of that would be. Usually I tend to see the median to be the better figure for comparison. Edit: Salaries also vary greatly depending on the country and the tax/benefits. E.g. a salary of 60000 Euros in Germany means that on top of that the employer mandatorily pays half of several social security contributions (that's health insurance, pension, unemployment insurance, care insurance) which amounts to roughly 10% extra (60000 Euros -> become about 66000) so when you compare that to say 60000 US$ you not only have to consider the current exchange rate but also these factors. In the US most "benefits" are not mandatory, no idea if they are part of the salary somebody will fill into such a questionnaire.
  10. dummzeuch

    Left side cannot be assigned to

    Wow, learned something new today. Sure, but I don't see the problem; Don't use them if you don't like them. I am not talking about interfaces that I design, but those I have to use (e.g. in the ToolsAPI or 3rd party libraries). Not much choice there. My own interfaces don't get properties. They usually have a getter that's called like the property would be (so MyValue rather than GetMyValue) and a setter with the standard name (SetMyValue).
  11. dummzeuch

    Left side cannot be assigned to

    For interfaces properties are purely syntactic sugar so you really don't have to use them if you prefer not to. You can just call the getters or setters directly. How is that a pain? Because once these properties exist in an interface, every class that implements the interface must also declare them. For a class at least properties are usually public/published while their getter/setter methods are private/protected, so one could argue that using a property reduces clutter. For an interface both the property and the getter/setter methods are public, so that argument doesn't apply.
  12. dummzeuch

    Left side cannot be assigned to

    TSomeClass private FFoo: string; public // with props property Foo: string read FFoo; // without props function Foo: string; ... function Foo: string; begin Result := FFoo; end; OK, I should have explicitly said "readonly properties with a getter method", because that's what I meant.
  13. dummzeuch

    Left side cannot be assigned to

    ... unless they are published and used via RTTI, e.g. in the Object Inspector or in some serialization code. Apart from that I partly agree. Especially the value of readonly properties is nearly zero and for interfaces they are a pain in the lower back.
  14. dummzeuch

    RDP and RD Web deployment of Delphi VCL apps

    So, what is your question? Do you want to know how to provide such a window list in your own application?
  15. You can't. But you can compile your own GExperts DLL and replace the one in your installation.
  16. dummzeuch

    IDE start randomly stops with error message

    If it occurs often enough, you might be lucky to catch it by running the IDE itself in the debugger and looking at the call stack. But beware: There are also quite a few exceptions during startup that are normal.
  17. dummzeuch

    Waiting for something without blocking the UI

    The problem here is, that in Delphi "blocking" means that the UI freezes, unless he calls Application.ProcessMessages, which has its own drawbacks (e.g. other events can be fired, some of which may not be desired).
  18. dummzeuch

    Appreciate the 'extra mile'..

    I think I said this before: The main reason for this was, that I forget about this problem until yet another Windows update breaks my Delphi installation again. Every time I had to remember the solution (that's why I blogged about it, so I could look it up) and then search for these bloody files. One time I have had enough... If it also helps others, that's great. To be fair: It's not Microsoft's fault but Borland's/Codegear's: These files do not belong into a system directory, but since we are stuck with this it's still annoying.
  19. The following is about a 32 bit Windows console application. I'm trying to improve performance for analyzing a huge Mono8 bitmap, stored in memory as a an array of bytes (no TBitmap involved). For each pixel the algorithm calculates the brightness for the pixel itself as well as a few surrounding pixels and writes the result to an array of byte. Doing this single threaded takes about 1300 ms. Since this can be done by multiple threads completely independently without the risk of race conditions I have split the work into n work packages, each processing some lines of the bitmap and each processed by a separate thread. The threads have been created in advance in a thread pool. Since there is no risk of race conditions I don't use any synchronization or locking mechanism during the processing. Synchronization is only necessary for assigning a work package to a thread and for signalling that a work package has been processed. This is the relevant code of the thread's execute method and the SetNext method called by the main thread to assign a work package to it: procedure TWorkerThread.Execute; begin inherited Execute; while not Terminated do begin FNewPackageEvent.WaitFor(500); FNewPackageEvent.ResetEvent; if Terminated then Exit; //==> FCritSect.Enter; try if Assigned(FData) and Assigned(FWorkCall) then FWorkCall(FData); finally FCritSect.Leave; end; end; end; procedure TWorkerThread.SetNext(_WorkCall: TWorkPackageCall; _Data: Pointer); begin FCritSect.Enter; try if Assigned(FData) or Assigned(@FWorkCall) then raise ESigException.Create('Programmer error: Package is already assigned.'); FData := _Data; FWorkCall := _WorkCall; FNewPackageEvent.SetEvent; finally FCritSect.Leave; end; end; FNewPackageEvent is a TEvent and FCritSect is a critical section, each unique to the TWorkerThread instance. A work package consists of a data pointer and a procedure pointer (not method pointer) to call. When a work package has finished processing a counter variable gets decremented like this: InterlockedDecrement(FCounter^); The main thread also processes one work package (it's also counted as one of the threads below) and then waits for the others to finish: while WorkPackageCounter > 0 do Sleep(WorkPackageCounter); (FCounter above is a pointer to WorkPackageCounter). Since every thread only processes one work package the counter starts as the number of threads. This works fine but I get some rather odd timing: Average time on 1 calls using 1 threads 1278 [ms] Average time on 1 calls using 2 threads 877 [ms] <------ Average time on 1 calls using 3 threads 1627 [ms] <------ Average time on 1 calls using 4 threads 1580 [ms] Average time on 1 calls using 5 threads 1511 [ms] Average time on 1 calls using 6 threads 1167 [ms] Average time on 1 calls using 7 threads 1438 [ms] Average time on 1 calls using 8 threads 1036 [ms] Average time on 1 calls using 9 threads 957 [ms] Average time on 1 calls using 10 threads 847 [ms] Average time on 1 calls using 11 threads 958 [ms] Average time on 1 calls using 12 threads 843 [ms] Average time on 1 calls using 13 threads 821 [ms] Average time on 1 calls using 14 threads 715 [ms] Average time on 1 calls using 15 threads 799 [ms] Average time on 1 calls using 16 threads 647 [ms] Average time on 1 calls using 17 threads 693 [ms] Average time on 1 calls using 18 threads 656 [ms] Average time on 1 calls using 19 threads 525 [ms] Average time on 1 calls using 20 threads 613 [ms] As you can see, distributing the work to 2 threads nearly halves the processing time, but adds some overhead which is what I would have expected. But distributing it to 3 threads all of a sudden takes more time than the single threaded approach. When adding more threads the processing time goes down again until it reaches some kind of minimum with 15 threads. This timing is from only a single call, but I also tried it with 100 calls and the average was about the same. The CPU is an Intel Xeon with 4 cores + Hyperthreading which gives me a logical 8 processor cores. Can anybody give me a hint what to look for to explain the oddity of 3 threads taking longer than 2 threads?
  20. I fixed a bug in the dxgettext executable which made it add wrong ressource string names to the po files which in turn made the msgmergePOT tool select wrong translations. You will have to compile your own executable to get this bugfix. The source code is in the project’s svn repository on SourceForge. Also I added scripts to generate partial German and French translations for Delphi 10, 10.1, 10.2, 10.3 and 10.4 and even added those partial translations for Delphi 10, 10.1, 10.2 and 10.4 (note that 10.3 is missing) to the repository. Warning: These translations may still be faulty.
  21. dummzeuch

    some dxgettext improvements

  22. All functions for copying / moving the contents of memory from one buffer to another seem to end up calling System.Move. (e.g. Windows.CopyMemory and Windows.MoveMemory). Is that really the fastest way to copy large amounts of data? Edit: This is about the 32 bit compiler for Windows. In my case these are Mono8 bitmaps with a resolution up to 5120x5120 = about 26 MB or BGR8 bitmaps with HD resolution (1920x1080 * 3 bytes = about 6 MB (or even BayerRG16 or Mono16 Bitmaps with up to 5120x5120 * 2 bytes = about 52 MB). These come in a buffer delivered from a camera API which must be returned as fast as possible, so I need to copy these pictures to another buffer for further processing and do it fast. The buffers don't overlap in that case which is something that Move takes into consideration, so there is some small amount of optimization possible. I think it might be possible to make it faster using some MMX/SSE instructions, but I am not familiar with that. I tried to google for this, but Google kept showing showing results for the C function CopyMem, as usual ignoring the "Delphi" part of my query (even when put in quotes).
  23. I understood that. I just tried it anyway just because that was easy to do and doesn't hurt. The pictures are huge: 5120 by 2000 with Mono8 pixels, so about 10 MB each. Sometimes they get even bigger: Up to 5120x5120 with RGP8 pixels. But that's very rare so far, so I don't care about performance for these at the moment. But I'm sure, since we have got this camera now, it will be used in more projects. I have already done that, as far as possible: As said before: This time it's a different program but the same basically applies: I try to avoid moving this data if possible at all. Hm, maybe using smaller buffers for only parts of the picture, as you suggested above, could help here. I'll have to think about that one.
  24. No, not that part. I have simply replaced some part that I thought might contribute a bit to the overall performance and was easy to replace. I timed the result and found that it didn't make any difference. Took me about 30 minutes so not much wasted effort. Through other means (improved algorithm and multithreading) I have already reduced the overall time for one work unit of the program to 1/3 compared to the original code. The program which I now used for the test is not the one I mentioned in the original question. That one has already gone into "production" about a month ago and the performance is "good enough".
  25. I finally came around to trying it with a 32 bit application and found no measurable improvement. Maybe I am doing something wrong, as there are several IFDEFS in the code which I don't understand what they are doing. Or maybe the move operation is simply not that important in the overall performance of the program. I did not do any specific timing for the move operation itself as I think it's pointless if it doesn't improve the performance of the program noticeably.