Jump to content

pyscripter

Members
  • Content Count

    780
  • Joined

  • Last visited

  • Days Won

    42

Posts posted by pyscripter


  1. Marco Cantu presented in CodeRage 2018 an implementation of Smart Pointers based on generics, similar to the one found in Spring4D. 

     

    It can be used as follows:
     

    var
      smartP: TSmartPointer<TStringList>;
     begin
       smartP := TStringList.Create;
       smartP.Value.Add('foo');
       TStringList(smartP).Add('foo2');

    I am using in my code a non-generics implementation from JclSysUtils

    var
      sl: TStringList;
      slSafeGuard: ISafeGuard;
    begin
      sl := TStringList(Guard(TStringList.Create, slSafeGuard));
      sl.Add('foo'):

    The second has the advantage that you do not have to use the Value property to get the object at the cost of having an extra declaration and being less elegant (?).   

    Are there any performance or other advantages to the Generics implementation?  Isn't the non-generics implementation faster and doesn't it generate less code?

     


  2. But here I am comparing the same app with/without debug dcus not between 32bit/64bit. 

    Actually I just noticed that the difference only appears with 32 bit in Delphi Rio.   Debug dcus make little difference in Rio 64bits or in Delphi Tokyo

    The surprising thing is that in this benchmark application, most of the computational time is spent inside external c code linked into the application.   Could it be that the debug dcus link to different c code in 32 bits Rio compared to dcus without debug info?

     

    Another finding was that in Delphi Tokyo, the benchmark runs significantly faster in 64bits than 32 bits  (quite the opposite with Davids zlib experience).


  3. I used to think that activating the compiler option "Use debug dcus" had minimal impact on performance.  I hadn't done any benchmarking but from experience I could not tell the difference in performance.  So I would include debug dcus even on release versions, so that full stack trace information would be available.   But in my recent tests regarding the performance of Regular Expressions, I found that activating this option would increase run times by as much as 70-80%.  

    • Does anyone has done any benchmarking or have any rough idea about this? 
    • Is the large performance hit specific to this case? 
    • Can you still get full stack trace information without using debug dcus?   (I am using jcl's Debug expert for exception reporting, with jdbg info linked into the executable).

     

    Example stack trace:

    Quote

    Stack list, generated 14/09/2018 15:56:54
    (0000F543){PyScripter.exe} [00410543] System.LocaleCharsFromUnicode (Line 39900, "System.pas" + 1) + $17
    (001CDF3F){PyScripter.exe} [005CEF3F] Vcl.Controls.TWinControl.CMEnabledChanged (Line 11672, "Vcl.Controls.pas" + 2) + $2
    (002B5F41){PyScripter.exe} [006B6F41] VirtualTrees.TBaseVirtualTree.CMEnabledChanged (Line 15752, "VirtualTrees.pas" + 1) + $2
    (0003F413){PyScripter.exe} [00440413] System.Generics.Collections.TListHelper.DoRemoveFwd4 (Line 2295, "System.Generics.Collections.pas" + 3) + $6
    (000081DB){PyScripter.exe} [004091DB] System.TMonitor.Exit (Line 18722, "System.pas" + 2) + $7
    (000A558C){PyScripter.exe} [004A658C] System.Classes.RemoveFixups (Line 9715, "System.Classes.pas" + 14) + $8
    (00007620){PyScripter.exe} [00408620] System.TObject.Destroy (Line 16985, "System.pas" + 0) + $0

     

     
    • Like 1

  4. PCRE, the regular expression engine used in Delphi has a large number of compile time options only few of which are exposed in the high-level (System.RegularExpressions) or the low-lever (System.RegularExpressionsCore) Delphi interface.  For example a useful PCRE option that is not exposed is the PCRE_UCP, which controls the meaning of \w \d etc.  When this options is set for example \w matches any Unicode letter or _ character.  If it is not set (in Delphi usage) it only matches ascii letter characters.   Class helpers can come to the rescue again.

     

    uses
      System.RegularExpressionsAPI,
      System.RegularExpressionsCore,
      System.RegularExpressions;
    
    type
      { TPerlRegExHelper }
      TPerlRegExHelper = class helper for TPerlRegEx
        procedure SetAdditionalPCREOptions(PCREOptions : Integer);
      end;
    
    procedure TPerlRegExHelper.SetAdditionalPCREOptions(PCREOptions: Integer);
    begin
      with Self do FPCREOptions := FPCREOptions or PCREOptions;
    end;
    
    
    type
      { TRegExHelper }
      TRegExHelper = record helper for TRegEx
      public
        procedure Study;
        procedure SetAdditionalPCREOptions(PCREOptions : Integer);
      end;
    
    procedure TRegExHelper.Study;
    begin
      with Self do FRegEx.Study;
    end;
    
    procedure TRegExHelper.SetAdditionalPCREOptions(PCREOptions: Integer);
    begin
      with Self do FRegEx.SetAdditionalPCREOptions(PCREOptions);
    end;
    

    Example usage: 

     

    Var
      RE : TRegEx;
      Match : TMatch;
    
    begin
      RE.Create('\w+');
      RE.SetAdditionalPCREOptions(PCRE_UCP);  // No match without this
      Match := RE.Match('汉堡包/漢堡包');
      if Match.Success then
        ShowMessage(Match.Groups[0].Value);

     

    • Like 3
    • Thanks 2

  5. One of the improvements in Delphi Rio is the upgrade of PCRE to version 8.42 and more importantly the inclusion of UTF-16 support on Windows.  What this means is that Delphi strings are no longer converted to UTF-8 and back when using Regular Expressions.  This blog post describes a benchmark of various regular expression options.   I wanted to see the impact of the Rio improvements and here are the results.   The results below use the test suite of the above mentioned article.

     

    Delphi 10.2:  Total Time:    12639.00 ms

    Delphi 10.3:  Total Time:    10614.00 ms (about 17% faster)

     

    Further improvement can be achieved by using PCRE Study.  Fir a bit of extra compile time you have significant execution benefits.  You need a class helper to use Study with TRegEx:

    type
      TRegExHelper = record helper for TRegEx
      public
        procedure Study;
      end;
    
    procedure TRegExHelper.Study;
    begin
      with Self do FRegEx.Study;
    end;
    

    You can call study after TRegEx,Create. Here are the results with Study.

     

    Delphi 10.2:  Total Time:    9863.00 ms

    Delphi 10.3:  Total Time:   7895.00 ms    (about 20% faster)

     

     

    • Like 2
    • Thanks 2

  6. Look at https://gitlab.com/teo-tsirpanis/gold-parser-Lazarus for a version 5 compatible Gold engine.  Version 5 grammars are not compatible with versions 1 engines.

    But IMHO the good old lex/yacc https://github.com/RomanYankovsky/ndyacclex can be more easily integrated with your Delphi projects.   No need to rely on third party libraries.  One could develop and test the grammar with GOLD I suppose and then translate it to lex/yacc.

    • Like 3
    • Thanks 1

  7. From the documentation: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/64-bit_Windows_Application_Development

    Making Your Components Available at Design Time and Run Time
    Following are the two ways the IDE decides whether or not a component is available for each platform. (Here "available" means appearing on the palette, and checked by the IDE. The IDE does not do any compile-time checking other than verifying the existence of component unit.)
    Both methods described here rely on data embedded in the Win32 run-time (or design+run-time) package that implements the components. The IDE cannot load packages built for platforms other than Win32 in the IDE, so the IDE must defer to the Win32 package for information.

    • The RAD Studio build system automatically embeds an RC_DATA resource in the Win32 package binary named PLATFORMTARGETS, which is a bitmask of the pidXXX constants in System.Classes.pas and reflects the package project's targeted platforms. The IDE reads this resource when the package is loaded and uses the resource data to decide, for example, whether or not to disable the component(s) in the palette when an unsupported platform is active.
      Targeting multiple platforms with a component package implies a contract between the component developer and the IDE. The IDE assumes that if a component package project targets multiple platforms and the developer distributes the Win32 run-time package to customers (and all the associated compilable and linkable files), the developer will also distribute all the necessary compilable, linkable, and run-time bits for the other targeted platforms as well.

    • Individual components can use the ComponentPlatformsAttribute class attribute to override the data in PLATFORMTARGETS, using a bitmask of the same constants in the Classes unit. For example:
      type

       [ComponentPlatformsAttribute(pidWin32 or pidWin64)] // Only supported on Win32 and Win64
       TMyComponent = class(TComponent)
       private
         ...
       end;
    

     

    So to get the components to be usable with other plagorms, all you need to do is before you compile the Design package to add the other platform to it. They won't be used but just being there makes the build system to include the appropriate resource flagging the package as usable for the platforms. I have tested this and it works!

    • Like 2
    • Thanks 3
×