-
Content Count
1497 -
Joined
-
Last visited
-
Days Won
152
Posts posted by Stefan Glienke
-
-
One could make it a const array of records where mass would be a number instead of a string
-
1
-
-
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
-
1
-
-
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.
-
1
-
-
This morning, I started the 14-day trial of Superluminal, and my first impression is very positive.
I have yet to run it against more than some tiny toy projects though
-
3
-
-
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.
-
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.
-
Because Pos is 1-based while SelStart is 0-based.
You could have read the documentation:
https://docwiki.embarcadero.com/Libraries/Athens/en/System.Pos
https://docwiki.embarcadero.com/Libraries/Athens/en/Vcl.StdCtrls.TCustomEdit.SelStart
-
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.
-
2
-
-
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
-
1 hour ago, snowdev said:that only works for Maintthread functions
It works very well for multithreading. You just have to change the sampling mode.
-
2
-
-
41 minutes ago, Tommi Prami said:As I recall ChatGPT gave virtually identical code also, but does not change the fact that I messed up...
This just underlines that GenAI and copyright is a delicate thing
-
2
-
-
I don't know what research RDP did (probably asking some GenAI
), 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.
-
3
-
-
As I mentioned in the thread you referred to, this interface no longer exists.
But as you might have noticed in the Spring commits in develop, I have my own Span implementation, and IList<T> has the method AsSpan, which returns this.
-
1
-
-
-
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;
-
2
-
-
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.
-
2
-
-
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.
-
5
-
-
Putting the actual functionality into a res file where you are loading it from at startup looks very sus, to say the least.
-
2
-
-
Be careful with the term reader and assuming that you can use mrew - in a consumer/producer pattern, the "reader" (i.e. consumer) is mutating a data structure (i.e. it pops an item)
-
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?
-
Because the language spec - pardon, the compiler - says so.
Constraints on generics are part of the declaration.
-
2
-
1
-
-
"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.
-
6
-
-
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
-
6
-
-
You could have given spring4d a try, which is actively maintained
-
6
-
CaretPositionRTTIProp.GetValue(Memo1) raises AV
in RTL and Delphi Object Pascal
Posted · Edited by Stefan Glienke
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.