Jump to content

Stefan Glienke

Members
  • Content Count

    1497
  • Joined

  • Last visited

  • Days Won

    152

Posts posted by Stefan Glienke


  1. Okay, the reason is because the CaretPosition getter is declared as cdecl (I have no clue why that is the case - I would assume some C++ compat because the result is a record) and the code for getting properties does not know about the calling conventions  of their setter and getter (because that is not part of their RTTI but only the code pointer to them) and thus always assumes standard calling convention.

    • Confused 1

  2. FWIW, such benchmarks should also run in parallel because especially string-related parsing is usually full of heap allocations that can suffer highly in multithreading.

     

    I am also sure that @Arnaud Bouchez could join the game and stomp all these libraries into the ground performancewise with mormot :classic_laugh:

    • Like 1

  3. I have not tested it with extensive data, but my first impression was that it is way more snappy.

    It does not have all the extensive capabilities of VTune, but if it does the important stuff way faster than VTune it's a pro IMHO.

     

    I also presume that it works fine with AMD CPUs.

     

    • Thanks 1

  4. 5 minutes ago, Der schöne Günther said:

    As far as I know, nowhere does it specify that keys must be unique.

    No, but according to RFC 8259, they *should* be unique.

     

    I just pointed out that by supporting that feature, there needs to be done more than simply adding pairs without any lookup.

    In fact, it looks like some implementations don't even allow adding duplicate names.


  5. The tests ignore some subtle differences in the implementations. While some implementations ensure that you don't create multiple pairs with the same name the System.JSON AddPair method simply ignores that.

     

    You can test that by adding a fLib.Add(SKey, SVal); after the loop in TTestSpeedRun.DoSubTestGen - some libraries will report 50000 items, while some report 50001 - System.JSON for example.

    The fact that JDO uses a linear search here is a bit disappointing and the reason it completely falls off the cliff on the generate test.


  6. On 5/10/2025 at 3:25 PM, pmcgee said:

    If you call a function/procedure that takes a const string, the function uses a new reference to the string.

    Yes, no surprise - because const[ref] forces a reference type variable to be passed by reference - build version three of your routines that have their parameter as var, and you will see.

     

    Also, your reasoning about what you see is mistaken - if you retrieve the address of a parameter or variable that resides in a register, the compiler will reserve stack space for it to retrieve the address of it.

    In the case of passing a const string as first and only parameter that one will be passed in eax on 32bit windows, or rcx in 64bit windows - calling @ on that parameter cannot give an address if that parameter stays in the register, hence the compiler generates code to reserve stack space, and puts the value there and retrieves that address.

    • Like 2

  7. If you are interested in collaboration:

    I could use a SIMD function that satisfies the following API:

     

    function PartitionRight(lo, hi: PDataType; out pivotPos: PDataType): Boolean;

     

    PDataType is the pointer to the type that is being sorted, such as PInteger or PDouble

    hi is exclusive. The result specifies whether the data has already been partitioned.

     

    For a start, a version for PInteger would suffice to run further benchmarks to evaluate if the impact is noticeable enough to justify an asm version

     

    The original reference implementation can be found here: https://github.com/orlp/pdqsort/blob/master/pdqsort.h#L329


  8. I don't know what research RDP did (probably asking some GenAI :classic_rolleyes:), but Spring4d does not contain thread-safe collections - for those needs, refer to libraries such as OTL or protect them by primitives in your own code according to your use-cases.

     

    I don't step into that territory because you cannot simply make general-purpose collections thread-safe. It already starts with simple things like: how do you protect a list where one thread adds/removes items and another iterates over it?

    It then requires a different API, and it's complex to design a general-purpose thread-safe collection library because everyone has their use cases, which you cannot simply combine.

    • Like 3

  9. 2 hours ago, HeartWare said:

    How does Rapid.TList<STRING> compare to THashSet<STRING> (only for checking if an entry exists in the list or not)? It'll be called thousands of times (the list itself will be pretty small - 5 or 10 entries)

    List always does linear search, which is O(n), while hashset does it in O(1) - however, considering the significantly higher cost of calculating the hashcode even with a very fast hash function (which the RTL does not use) and the length of the string for a small amount of entries linear search beats a hashtable. In theory, if the entries are not changed that often, one could sort the list and use binary search. But that also requires a fast, optimized, inlined BinarySearch implementation, which the RTL does not have, IIRC.

     

    P.S. Rapid.Generics.TList<T>.IndexOf is broken - line 19503 causes an endless loop. The same defect exists in InternalIndexOfRev.

    How to repro:

     

    procedure IndexOfEndlessLoop;
    begin
      var list := Rapid.Generics.TList<string>.Create;
      for var i := 0 to 1 do
        list.Add(TGUID.NewGuid.ToString);
      list.indexOf(list[1]);
    end;

     

    • Like 2

  10. One thing that I dislike about the Rapid implementation is the ton of magic numbers and the fact that the used hash algorithm is documented nowhere - I assume some form of Robert Sedgewick hash (which I could not find a formal description of anywhere on the internet).

    That makes it hard to verify its correctness and behavior. :classic_sad:

    • Like 2

  11. I am not implying anything or accusing you. Still, in the age of supply chain attacks and smuggling malicious code into open source repositories, anyone that blindly trusts some binary code they cannot build from source is acting grossly negligent.

    • Like 5

  12. On 4/2/2025 at 12:42 AM, Alex7691 said:

    One specific scenario where I replaced the std TDictionary with the Rapid.Generics one (a notification bus where a dictionary is used to map the instances) had a performance increase of 10x or more

    I am very curious about this particular scenario. Can you tell me the dictionary's key and value types and usage? Is it mostly looking up values or adding/removing items?


  13. I was just curious. I expected the fact that it's a drop-in replacement to be a reason.

    Rapid is quite an achievement and damn those collections are fast - I use them to challenge my implementation from time to time.

    The design decisions are different, and for the extensive API of spring, I have to sacrifice a few nanoseconds here and there, as much as I dislike that :classic_laugh:

    • Like 6
×