-
Content Count
1497 -
Joined
-
Last visited
-
Days Won
152
Everything posted by Stefan Glienke
-
While I appreciate your recommendation this would not solve anything here - the performance difference is not from a poor getter implementation but from the fact that it's a call instead of directly indexing into the backing array. Since spring4d collections are all interfaces they hardly are any faster wrt to calling the getter.
-
64bit RTL patches with Intel OneApi and TBB
Stefan Glienke replied to RDP1974's topic in RTL and Delphi Object Pascal
Then please put the DLL projects into the repo with documentation on how to get the missing pieces to produce them ourselves instead of distributing binaries. As for the RTL routines - as mentioned FillChar already has been improved in 11.1 (and hopefully will get another final improvements - some of which are detailed here: https://msrc-blog.microsoft.com/2021/01/11/building-faster-amd64-memset-routines/). Pos has also been improved (mostly Win64 is affected by this as the new code is basically the purepascal code of what was the asm implementation for Win32). Hopefully for 12, we will get an improved Move I was working on (using SSE2 as that is the supported instruction set RTL can assume). Because Move handles forward/backward and overlap it covers what memcopy and memmove do. That leaves CompareMem which I already looked into in context of faster string comparison, UpperCase and Replace. -
Probably with https://github.com/MahdiSafsafi/DDetours
-
I Broke Delphi ->> Low bound exceeds high bound & Duplicate case label if you swap'em (Case Z of) Table error
Stefan Glienke replied to Al T's topic in Algorithms, Data Structures and Class Design
Because its wrong - you are handling the result of v shr 32 as if it was v div 10000000000 -
64bit RTL patches with Intel OneApi and TBB
Stefan Glienke replied to RDP1974's topic in RTL and Delphi Object Pascal
First of there is no 10.5 - I assume you meant 11. That's like the mother of pointless benchmarks. We know that default MM is prone to problems with heavy multithreading. Test with FastMM5 because that has addressed that issue. For using TBB, I think it was mentioned in another thread that also the memory footprint should be considered. Part of the improvement might come from the better system routines such as Move (FillChar has already been improved in 11.1) - I have been working on an improved version but I am afraid we will not get it before Delphi 12. Also - I think I mentioned this before: in the age of supply chain attacks and malicious code being distributed via open source platforms, I would be very careful about using some binaries. You mentioned before how you compiled them: why are you reluctant to post the code on GitHub so everyone can compile it themselves? -
I Broke Delphi ->> Low bound exceeds high bound & Duplicate case label if you swap'em (Case Z of) Table error
Stefan Glienke replied to Al T's topic in Algorithms, Data Structures and Class Design
What? A case is slower than chained if statements in such a case because it uses a series of add and sub instructions combined with conditional jumps. That usually causes data dependency. Also the function using case is wrong - you must not use shr 32 and then compare that to base10 values. As for the other version: when checking if the number is in integer range, do the less than 0 check once and then do an Integer hardcast for the other checks - that avoids the full 64bit compare that needs two cmp and conditional jump instructions on 32bit. Also FWIW the check against maxlongint is unnecessary. -
I Broke Delphi ->> Low bound exceeds high bound & Duplicate case label if you swap'em (Case Z of) Table error
Stefan Glienke replied to Al T's topic in Algorithms, Data Structures and Class Design
That code reminds me of what I have seen in SysUtils _IntToStr64 and _IntToStr32 (getting the number of digits) Also see https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 -
Because that is not pascal-ish! /s 🙄 P.S. Yes I know about proposals to make it look pascal-ish - I even think we discussed that in another thread already.
-
Ask for comments to improve this code
Stefan Glienke replied to Berocoder's topic in Algorithms, Data Structures and Class Design
People overuse generics and forget that the implementation often does not need generics at all: type TSupport = class helper for TObject private function __Supports(out ResObj: TObject; cls: TClass): Boolean; public function Supports<T: class>(out ResObj: T): Boolean; inline; end; function TSupport.__Supports(out ResObj: TObject; cls: TClass): Boolean; begin if Assigned(Self) and Self.InheritsFrom(cls) and not ((Self.InheritsFrom(TBoldObject)) and TBoldObject(Self).BoldObjectIsDeleted) then begin ResObj := Self; Exit(True); end; ResObj := nil; Result := False; end; function TSupport.Supports<T>(out ResObj: T): Boolean; begin Result := __Supports(TObject(ResObj), T); end; This code will not cause any bloat at all (in the final executable - see below for the situation during compilation though). What @ventiseis wrote is correct - the issues with long compile-time and possibly running ouf of memory (more so under the LLVM based compiler because they have a larger memory usage already) are real. They are caused by the compiler first compiling unit by unit and stuffing everything generic being used into each dcu just to (possibly) remove it again later during link time. Linker however will only remove exact identical duplicates such as if you have TList<TFoo> in multiple units executable will only contain it once, but it will also contain TList<TBar> and TList<TQux> even though they are also just lists for objects. Since XE7 most methods on TList<T> are marked as inline and unless you are using runtime packages they are not being called in your executable but the internal TListHelper ones but since all RTL classes have $RTTI turned on the binary will still contain all these methods. You only partially get rid of them by using {$WEAKLINKRTTI ON} which you need to put into each and every unit (years ago you could put that into the dpr and it affected all units but that was actually a compiler bug that made flags with scope local being global - but any unit that changed them then also changed them globally which caused quite some weird defects) That is why I did the huge refactoring in Spring4D regarding collections and the generic container registration API. If you use a list from spring with a thousand different classes the binary will only contain the code for the list once unlike with the RTL where you would have it a thousand times The issues are known and reported but obviously are not severe enough or too complex (especially the second one would require some architectural changes to how the compiler deals with generics): https://quality.embarcadero.com/browse/RSP-16520 https://quality.embarcadero.com/browse/RSP-18080 -
Looks to be an issue with https - over http it works
-
Function with 2 return values ?
Stefan Glienke replied to Henry Olive's topic in RTL and Delphi Object Pascal
A static array of Double with the size 3 - exact type name would be context-specific and since you are not giving any context I cannot name it. -
Function with 2 return values ?
Stefan Glienke replied to Henry Olive's topic in RTL and Delphi Object Pascal
A pair is a tuple where n is 2 - so yes it is a tuple -
It was a must if you have done a bit more than just registering a component (such as custom designers and stuff) because then the package requires designide.bpl which you must not ship. Yet the IDE even in 11.1 creates new packages as design&runtime 🙄
-
does SetLength for an array actually release memory?
Stefan Glienke replied to dummzeuch's topic in RTL and Delphi Object Pascal
That's up to the implementation of ReallocMem - the one that comes with Delphi (FastMM4) (I just looked into getmem.inc) has this comment: -
TMethodImplementation and its uses
Stefan Glienke replied to pyscripter's topic in RTL and Delphi Object Pascal
FWIW I only use this to make my multicast events work on platforms where I don't have exactly that: handcrafted assembly code to do the parameter passing. And these run hundreds of times faster than using RTTI. You can turn on using RTTI instead of the asm code in Spring.Events Here is a simple benchmark result: asm (win32) Event invokes/ms: 14925 rtti Event invokes/ms: 205 I have already started digging more into the TMethodImplementation class to optimize its use for those platforms where I don't have the handcrafted asm. There are also libraries that avoid the overhead of the Delphi RTTI to do dynamic invocation by handling all the low level details: https://github.com/d-mozulyov/Tiny.Library#rtti but that requires doing the parameter passing via some stubs written in c asm -
Counting newlines in a huge string in parallel: improving Parallel.For())
Stefan Glienke replied to Gerben Abbink's topic in OmniThreadLibrary
You don't need to manually create tasks - just use a TParallel.For and do proper partitioning - I wrote an answer on Stackoverflow about that subject some while ago. The code there which did some array processing should be easily be adaptable to your usecase -
Cromis.DirectoryWatch range error
Stefan Glienke replied to Tom F's topic in RTL and Delphi Object Pascal
The WParam of TMessage is ultimately of type NativeUInt while the WParam parameter is of type Longint. Since Delphi 11 the default Debug config has Range and Overflow checks enabled which causes any signed to unsigned or vice versa assignment to possibly raise a range check error. Strictly speaking any assignment of signed to unsigned and vice versa is a potential defect - you can reveal them by turning W1071 on with {$WARN IMPLICIT_INTEGER_CAST_LOSS ON} -
FreeAndNil() - The Great Delphi Developer Debate
Stefan Glienke replied to AlexBelo's topic in Tips / Blogs / Tutorials / Videos
You forgot "no calling each other nazi" (see Godwin's law) -
FreeAndNil() - The Great Delphi Developer Debate
Stefan Glienke replied to AlexBelo's topic in Tips / Blogs / Tutorials / Videos
Using FastMM with the setting to mark freed memory with a certain pattern ($80808080 by default iirc) would have revealed that issue within a few minutes fwiw. -
Do you need an ARM64 compiler for Windows?
Stefan Glienke replied to Lars Fosdal's topic in Cross-platform
By that logic the Delphi team must be located near Piacenza 🙄 -
EMonitorLockException help needed
Stefan Glienke replied to luebbe's topic in RTL and Delphi Object Pascal
Only from TMonitor.CheckOwningThread (indirectly via the lookup mechanism from ErrorProc in ErrorAt) which gets called from two places: TMonitor.Exit and TMonitor.Wait. -
EMonitorLockException help needed
Stefan Glienke replied to luebbe's topic in RTL and Delphi Object Pascal
My point is that posting a red herring won't get you much help. First task should be to get a proper call stack because that will directly point you to the source location that causes it without the need to poke in the dark hoping to find it. The exception is clear and this happens when a monitor lock is being exited or waited on from a different thread than the one that entered it. -
EMonitorLockException help needed
Stefan Glienke replied to luebbe's topic in RTL and Delphi Object Pascal
The Eurekalog call stack makes zero sense compared to the code on github. Either you are using some outdated code or modified something yourself. There is nothing monitor in TThreadSafeQueue.Enqueue. It is using a critical section -
TStringHelper.IndexOfAny( array of string, ...): Why is this private ?
Stefan Glienke replied to Rollo62's topic in RTL and Delphi Object Pascal
My profile shows what I am using in production at work. That does not mean I don't also have access to 11.1 which had this issue addressed 😉 -
TStringHelper.IndexOfAny( array of string, ...): Why is this private ?
Stefan Glienke replied to Rollo62's topic in RTL and Delphi Object Pascal
No.