-
Content Count
1518 -
Joined
-
Last visited
-
Days Won
154
Everything posted by Stefan Glienke
-
Pointer casting with NativeUint
Stefan Glienke replied to duzzell's topic in Algorithms, Data Structures and Class Design
Somehow I cannot believe that ZEOS did not properly support 64bit until now - you must have been using some old code -
TParallelArray Sort Performance...
Stefan Glienke replied to Steve Maughan's topic in RTL and Delphi Object Pascal
Quicksort with comparer calls compiled by a mediocre compiler operates far below L3 cache speed. -
Records as TDictionary keys
Stefan Glienke replied to balabuev's topic in RTL and Delphi Object Pascal
Of course - TDictionary<K,V> is hashtable based, so it needs GetHashCode and Equals -
Custom Managed Records and Default(T)
Stefan Glienke replied to rgdawson's topic in Algorithms, Data Structures and Class Design
There should not be any temp, nor assign call tbh. Check out this code: {$APPTYPE CONSOLE} uses SysUtils; type TMyRec = record x: Integer; class operator Initialize(out dest: TMyRec); class operator Finalize(var dest: TMyRec); class operator Assign(var left: TMyRec; const[ref] right: TMyRec); end; function MyDefault: TMyRec; begin Writeln('default - ', IntToHex(IntPtr(@Result))); Result.x := 0; end; class operator TMyRec.Initialize(out dest: TMyRec); begin Writeln('init - ', IntToHex(IntPtr(@dest))); end; class operator TMyRec.Finalize(var dest: TMyRec); begin Writeln('finalize - ', IntToHex(IntPtr(@dest))); end; class operator TMyRec.Assign(var left: TMyRec; const[ref] right: TMyRec); begin Writeln('assign'); end; procedure Main; var r: TMyRec; begin r := MyDefault; end; begin Main; end. Now we can argue why there is no assign call because we are assigning the result of the MyDefault function to r. But even though we have declared an assign operator it does what it always does with managed return type - passing it as hidden var parameter. I said this before and I say it again - CMR are broken as designed and personally I stay the heck away from them. I remember some years ago there was a question on SO about struct default ctors serving as default initializers and why C# does not have them and I don't remember if it was Jon or Eric explained that it would cause all kinds of trouble. Edit: Ah, here it is: https://stackoverflow.com/a/333840/587106 - eventually they added them in C# 10 but there is quite some extensive language spec - when I asked for the CMR spec it was all crickets. FWIW the Delphi implementation suffers from exactly the situation that Jon describes - allocate a dynamic array of some CMR and watch all the initializers run. Which is completely bonkers - C# 10 does not do any of that for array allocation - see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/parameterless-struct-constructors#array-allocation -
Custom Managed Records and Default(T)
Stefan Glienke replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Already reported in 2021 -
MAP2PDB - Profiling with VTune
Stefan Glienke replied to Anders Melander's topic in Delphi Third-Party
you can generate a dpk with the help of System.SysUtils.GetPackageInfo -
MAP2PDB - Profiling with VTune
Stefan Glienke replied to Anders Melander's topic in Delphi Third-Party
Recompile the RTL yourself using source\rtl\buildrtl.bat and generate map file - that's how I used to do it until Anders added jdbg support. -
Recursive anonymous functions
Stefan Glienke replied to Primož Gabrijelčič's topic in Algorithms, Data Structures and Class Design
There is no local variable - on the source code level, yes there is, but implementation wise they live inside the heap memory of the compiler generated instance. That's why captured variables never appeared in the local variables view until recently when the kinda implemented support for it. -
Watch me coding in Delphi on YouTube
Stefan Glienke replied to silvercoder79's topic in Tips / Blogs / Tutorials / Videos
omg, no! Followed by "How do I fix these random Access Violations that appear in my code" -
Recursive anonymous functions
Stefan Glienke replied to Primož Gabrijelčič's topic in Algorithms, Data Structures and Class Design
To understand this, you need to understand how anonymous methods are implemented. The compiler implements them by creating a class that inherits from TInterfacedObject. The anonymous method type is a special interface with one method called Invoke, which has the signature of the anonymous method type. When you add ReportMemoryLeaksOnShutdown := True to the code above you will see that it reports one instance of a class called MakeFib$ActRec - that is the class name of the compiler-generated class for the anonymous method. The class also contains fields for every captured variable - in this case the local variable fib is being captured with holds the reference to itself so this is the circular interface reference that causes the memory leak. To demonstrate here is the code as the compiler implements it: type MakeFibAnonClass = class(TInterfacedObject, TFunc<integer,int64>) fib: TFunc<integer,int64>; function Invoke(value: integer): int64; end; function MakeFibAnonClass.Invoke(value: integer): int64; begin if value < 3 then Result := 1 else Result := fib(value - 1) + fib(value -2); end; function MakeFib_Impl: TFunc<integer,int64>; var obj: MakeFibAnonClass; begin obj := MakeFibAnonClass.Create; obj.fib := obj; Result := obj.fib; end; -
Methods to convert a string TValue to the desired simple type (Like Integer, Float, DateTime);
Stefan Glienke replied to dmitrybv's topic in RTL and Delphi Object Pascal
Convert<T> from TValueHelper in Spring. See https://bitbucket.org/sglienke/spring4d/src/2.0.1/Source/Base/Spring.pas#lines-651 -
get the source from SourceForge open Projects\DelphiXx120\GExpertsRS120.dproj compile run Binaries\Register-GExperts-XX120.cmd restart IDE
-
updated Delphi64RTL intel ipp onetbb
Stefan Glienke replied to RDP1974's topic in RTL and Delphi Object Pascal
You *must not* remove that line - Move in Delphi allowed to be called with negative Count (a possible result of some size calculation), resulting in a no-op in the System implementation. Passing a negative number to most C++ implementations will result in passing a value >2mio because their size parameter is unsigned. Also, the performance difference is hardly about that little check but the ippsMove_8u implementation. -
updated Delphi64RTL intel ipp onetbb
Stefan Glienke replied to RDP1974's topic in RTL and Delphi Object Pascal
ippMove is not much faster than System.Move in Delphi 12. In fact, it performs noticeably worse on small sizes (below 1k) and for some reason completely falls off the cliff on sizes that are >20k running 2-4 times slower. -
Dynamic array used as a queue. Memory fragmentation?
Stefan Glienke replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
Only on 64bit though - on 32bit the size of TDynArrayRec is 8 byte, if the memory manager getmem returns 16byte aligned memory that makes the elem[0] 8byte aligned. This is why i said that the RTL has to take care of it - the same is the case for strings. Relying only on the memory manager which is replaceable prevents the RTL from doing things that it could if certain data would have certain alignments. Using SSE for some string handling functions and such. -
Dynamic array used as a queue. Memory fragmentation?
Stefan Glienke replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
That would be true if dynamic array allocation would be done in a way that ensures that element [0] would be at a 16 byte aligned address, which is not the case -
Dynamic array used as a queue. Memory fragmentation?
Stefan Glienke replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
Not exactly, it moves everything in the array to the front and then calls SetLength with the new length. What that does internally depends on the refcount of the array. If it's 1, then it does a Realloc (shrinking in place, though depends on the memory manager what exactly happens, typically for a small downsize it does it in place, thus basically resulting in a no op) If it's greater than 1 it allocates a new block and copies the content over - I would say calling SetLength inside of Delete is a bug because everything was already moved in place thus the behavior of SetLength is not to be desired in this case. In fact this leads to some corrupted copy lying around Reported https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-1532 Edit: apparently this is already known since 2020 - https://quality.embarcadero.com/browse/RSP-27870 -
Devin AI - Is it already happening?
Stefan Glienke replied to FreeDelphiPascal's topic in General Help
Because things like Clean room design exist to minimize the chances of any copyright infringement. There have been lawsuits over "similarly enough looking" code in the past. Also, the simple fact that gen AI does not care about any license attribution which you would have to follow if you take any source code with one of the major permissive licenses that still require attribution. -
Devin AI - Is it already happening?
Stefan Glienke replied to FreeDelphiPascal's topic in General Help
It's really embarrassing to see how many people who work in software development don't know how generative AI works and are being fooled by it like an average TikTok teenager. -
Devin AI - Is it already happening?
Stefan Glienke replied to FreeDelphiPascal's topic in General Help
-
This and also a kind of limited approach given that the lifetime of all those UI elements is bound to the application lifetime and they are all singletons (meaning that you cannot have more than one instance of say ITestDlg)
-
Devin AI - Is it already happening?
Stefan Glienke replied to FreeDelphiPascal's topic in General Help
The last thing I know of is that Devin AI was fake (that info is from April 2024 when the entire developer community was all over the demo they showcased). Do you know more? -
how to filter on source files using VTune?
Stefan Glienke replied to merijnb's topic in Delphi Third-Party
Changing anything with the map file will only remove the names, the functions being called will still be in the sampling result because VTune is a sampling profiler. Given that obviously, your performance problem was not with these functions they should not be a significant part of the result percentage-wise - if they are, they are part of the issue. -
Unicode NBSP(u00A0) No-Break Space character for 64-bit
Stefan Glienke replied to sp0987's topic in RTL and Delphi Object Pascal
Can't be asked - I am using the sfw (safe for work) version 😇 -
Unicode NBSP(u00A0) No-Break Space character for 64-bit
Stefan Glienke replied to sp0987's topic in RTL and Delphi Object Pascal
FWIW the assembly implementation of that function is pointless given you can do it in a way more readable way - also performance cannot be a reason given the following call to mem_write causes a temporary heap allocation to convert your hex_code variable into an AnsiString. Quickly slapped together (anyone who wants to further optimize this - be my guest, i cba right now): type hex_code = Array [1 .. 4] of AnsiChar; function Int2Hex(c: Word): hex_code; const HexChars: array[0..15] of AnsiChar = '0123456789ABCDEF'; var i: NativeUInt; begin i := c; Result[4] := HexChars[i and $0F]; i := i shr 4; Result[3] := HexChars[i and $0F]; i := i shr 4; Result[2] := HexChars[i and $0F]; i := i shr 4; Result[1] := HexChars[i and $0F]; end; and then instead of mem_write with AnsiString as the first argument use one that writes 4 bytes at once.