Jump to content

Anders Melander

Members
  • Content Count

    2850
  • Joined

  • Last visited

  • Days Won

    156

Posts posted by Anders Melander


  1. I have a component which contains sub-properties; I.e. a component property which is itself an object that contains its own properties. The object is derived from TPersistent and one of its properties is an event. The problem I'm having is getting this event to appear in the object inspector.

     

    I'm pretty sure that I had it working at one point but whatever I've tried now I can't get the event property to appear in the OI.

    image.png.94fabe2b40d3cf5ea2f2c940c2ab14a6.png

    FWIW, it works without problems in the Lazarus IDE.

     

    I've looked through the source of the few ToolsAPI units we have available but I haven't found any clues there. As far as I can tell it should work.

     

    So what am I missing?

     

    The following source reproduces the problem:

    unit FooBar.Reg;
    
    interface
    
    uses
      Classes, DesignIntf;
    
    type
      TTestSub = class(TPersistent)
      private
        FOnEvent: TNotifyEvent;
        FTest: string;
      public
        procedure Assign(Source: TPersistent); override;
      published
        property Test: string read FTest;
        property OnTestEvent: TNotifyEvent read FOnEvent write FOnEvent;
      end;
    
      TTest = class(TComponent)
      private
        FSub: TTestSub;
        procedure SetSub(const Value: TTestSub);
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        property Sub: TTestSub read FSub write SetSub;
      end;
    
    procedure Register;
    
    implementation
    
    procedure Register;
    begin
      RegisterComponents('FooBar', [TTest]);
    end;
    
    { TTest }
    
    constructor TTest.Create(AOwner: TComponent);
    begin
      inherited;
      FSub := TTestSub.Create;
      FSub.FTest := 'Hello world';
    end;
    
    destructor TTest.Destroy;
    begin
      FSub.Free;
      inherited;
    end;
    
    procedure TTest.SetSub(const Value: TTestSub);
    begin
      FSub.Assign(Value);
    end;
    
    { TTestSub }
    
    procedure TTestSub.Assign(Source: TPersistent);
    begin
      FOnEvent := TTestSub(Source).OnEvent;
    end;
    
    end.

     


  2. 8 minutes ago, snowdev said:

    Your solution works for 64bits applications?

    Yes it does - but map2pdb just produces the pdb files required by the profilers.

    Profilers that works with pdb files includes Intel VTune and AMD μProf.

     

    I believe μProf works with both Intel and AMD processors while VTune only works with Intel processors but use the one that matches your processor to get the most precise results.   I use VTune myself.

     

    Ask if you need instructions on how to get started. The process is very easy once you know how to do it but it can be challenging to get to that point 🙂


  3. 56 minutes ago, Rollo62 said:

    Yes you are right. VCL/FMX unit linkage is comparable to DB and Windows-Service.
    Also tests for other platforms are completely superfluous, especially if Win32 ASM code is used in the library, nothing can go wrong here.
    I revoke all my silly notes above, they seem to be too stupid.

    1940673266_Reductioadabsurdum.thumb.jpg.fc09f84d507a8081cb38c852fb5cf677.jpg


  4. 2 hours ago, Tommi Prami said:

    I had no intention of taking credit for something that isn’t mine.

    Yet you did.

     

    If you couldn't remember where you got the code from then you simply shouldn't have posted it without proper attribution.

    As it is now the code is nearly identical so it's not just "inspired" or "influenced". That's not a problem in itself, it's open source after all, but you have to at least keep the original license which is "MPL 1.1 or LGPL 2.1 with linking exception". I've created an issue at your repo to get that fixed.

    image.thumb.png.82e8dd34085f3da3ccaeb1b4cebb98ba.png

     


  5. 38 minutes ago, limelect said:

    The US government says it would be better for them [...]

    In other news, Lazarus, the North Korean hacker group has released a statement saying it would be better for them if people would please click on the link in that email ebay has just just sent them asking to update their account details.

    "There's too much mistrust in the world today" said Park Jin Hyok, a spokeperson for Lazarus. "Just click it, godammit".

    • Haha 3

  6. 6 hours ago, Tommi Prami said:

    Depending on your CPU, you might need to set Affinity mask for the threads.

    For benchmarking, sure. But otherwise I would think it would be better to let Windows manage that.

     

    6 hours ago, Tommi Prami said:

    Made siple unit top get Affinities: https://github.com/TommiPrami/Delphi.ProcessAffinity.Utils

    That code sure does look a lot like this one...

    https://github.com/graphics32/graphics32/blob/4fbc8d2a3083e42a00ca776eaa52af7cab2de34a/Source/GR32_System.pas#L399

    • Like 1

  7. 5 minutes ago, snowdev said:

    -Change TCriticalSection locking for TLightweigtMREW gabr42 version

    Do you really need reentrant locks? If not then just use the standard version. There's no need to complicate thing further.

     

    Also MREW only makes sense if you have more readers than writers. For single writer & single reader there's no reason for it.

    As I read it you are considering using a pool of reader in which case MREW might very well make sense (or "just" use a lock free queue).

     

    Btw, if you don't need to process the work packets "in order" then things become a little easier since a lock-free stack is often simpler to implement than a queue.

     

    9 minutes ago, snowdev said:

    The external API which I consume returns PWideChar and is a pain to work in certain circumstances…

    A PWideChar doesn't necessarily mean that the source string is a Widestring. It would very well just be a pointer to regular unicode string.

    It's just not common to explicitly use PWideChar anymore since it is the same as PChar on unicode Delphi. Regardless, the message was more that you should avoid WideString unless you have a reason to use it. You can't really do anything about what your external lib uses internally.

     

    Good luck. You have many hours of debugging ahead of you 🙂 


  8. 34 minutes ago, snowdev said:

    Not exactly, using ReportMemoryLeaksOnShutdown didnt take any leak running the tests… every queue format release their resources.

    I didn't investigate but I got a lot of leaks reported when existing the application when running in the debugger.

     

    36 minutes ago, snowdev said:

    I’ll take a look into that, usually dont. This reason I dont included in the given example… every thread became up on the app initialization.

    Okay.

    It's expensive to start a thread but if you are launching the threads at application startup then it doesn't matter. If you create them on-demand then I would use TTask instead. The first task will take the worst of the pool initialization hit.

     

    39 minutes ago, snowdev said:

    I dont know a profiling lib for Delphi, but I’ll measure them with stopwatches.

    https://en.delphipraxis.net/search/?q=profiling

     

    41 minutes ago, snowdev said:

    I just use locking because I dont know if there could have a deadlock when other thread is pushing and the worker is popping, so I do it just in case.

    If you use a lock-free structure then you don't need locking. Hence the "free" in the name 🙂

    And FTR, the term deadlock means a cycle where two threads each have some resource locked and each is waiting for the other to release their resource. I think what you meant was race condition; Two threads modifying the same resource at the same time.

     

    54 minutes ago, snowdev said:

    About strings I could switch to PWideChar aswell, I use string for ease.

    PWideChar is supposedly a pointer to a WideString? In that case, please don't. WideString is only for use in COM and it's horribly slow.

    No, what I meant was that instead of using dynamic strings (which are relatively slow because they must be allocated, sized, resized, freed, etc.) use a static array of chars: Buffer: array[BufferSize] of char. You will waste some bytes but it's fast.

    • Like 1

  9. 4 hours ago, snowdev said:

    Could I be measuring the performance incorrectly?

    Yes.

    • For one you are running all the tests concurrently which means that you will be penalizing the tests that start later because they will be competing for CPU against the test that are already executing. Execute each test and wait for it to finish before you start the next test.
       
    • You also seem to have massive memory leaks which probably means that some of the test have an unfair advantage because they don't consume time releasing their resources.
       
    • If you are using thread pools (I'm not sure that your are (if not, you should be)) then you should ensure that the thread pool has been spun up before you start the test. Otherwise you will penalize the first threads with the startup overhead.
       
    • Instead of just looking at the time from start to end and then guessing about why it is fast/slow/whatever, profile your code so you can see exactly where the bottlenecks are. Do this for each individual algorithm in turn.

    Apart from that, for something as simple as this, you don't need locking and you definitely don't need to use the Windows message queue as a work queue.

    Use a simple lock-free fifo queue instead.

    You could even use a fixed size lock-free ring buffer (just an array of records with two integer values as in/out indices). The fixed size buffer and the records would eliminate the allocation overhead of the queue itself. You should probably also try to eliminate the use of string and replace it with fixed size buffer if possible.

    • Like 5

  10. 2 hours ago, Stefan Glienke said:

    "It's not the bottleneck, therefore, I don't care" is the reason why Embarcadero does not care to implement anything that is reasonably optimized

    I really think it's more a question of lack of expertise, limited resources, and priorities.

     

    I think they would if they could but since they can't communicate that to the customer they instead come up with excuses that comes across as if they don't care.

    • Like 3

  11. 2 minutes ago, David Heffernan said:

    The potential bottleneck is the RTL dictionary class. Which happens to be a generic type.

    Thanks for explaining that to me. Now I understand everything exactly like I did before.

     

    I don't have any code where anything in system.generics.collections or system.generics.defaults is anywhere near the bottleneck

    Better?


  12. 14 minutes ago, Alex7691 said:

    I can just toggle this compiler directive globally and the 3+ MLOC application can be built either using Rapid generics or std System.Generics.Collections, which is a major bonus. At anytime I can just switch this off with minimal impact (e.g. let's say EMB releases a new faster System.Generics.Collections in Delphi 12+x?)

    Nice!

    Unfortunately I don't have any code where generics is anywhere near the bottleneck or I would have had a go with it.

    • Like 1

  13. Use an interposer for TDataModule.

     

    The datamodule base class (no DFM):

    unit Foo.Bar;
    
    interface
    
    uses
      Classes;
    
    type
      TBaseDataModule = class(TDataModule)
      private
        FFoobar: integer;
      public
        property Foobar: integer read FFoobar write FFoobar;
      end;
    
    implementation
    
    end.

     

    Your datamodule:

    unit Whatever;
    
    uses
      Classes, etc. etc., ...
      Foo.Bar;
    
    type
      // The interposer
      // You could have declared it in the Foo.Bar unit but I prefer to declare it explicitly
      // everywhere it's used to make it clear what is going on.
      TDataModule = TBaseDataModule;
    
    // Your regular TDataModule stuff
    type
      TMainDataModule = class(TDataModule)
      ...
      end;
    
    etc.

     


  14. 16 hours ago, Darian Miller said:

    I'd start with private const and end with private fields.

    Me too - and I would most often also start with the class vars and types. Of course it depends on the size and structure of the class; For a large class I would probably try to keep associated stuff close together as an overriding principle.

×