-
Content Count
1487 -
Joined
-
Last visited
-
Days Won
151
Everything posted by Stefan Glienke
-
Must be very unproductive and frustrating the way you handle things - it is known that humans are terrible at context switching.
-
Why is public class method marked as used, while it's not actually used?
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
There are several factors - RTTI is one of them, another is generics, in combination they can be quite terrible. Example: A class is using a TList<something> as a field - TList<T> has RTTI enabled which causes all code for that TList<something> to reside inside the binary even though calls to Add, Delete and alike are inlined and go directly to those non generic TListHelper methods. Now multiply that with all lists and dictionaries in RTL/VCL and your code and you have the issue. Having said that - this is just one case which I was working on as author of a library that makes extensive use of generics and I don't want to be a big contributor to that issue. Putting {$WEAKLINKRTTI ON} into the project file can reduce the bloat a bit because this enables the linker to remove all methods that are not being used. An empty FMX application on Win32 is 8.5MB in release config and contains way over 2MB just from System.Generics.*. With that option you can at least reduce this to 7.4MB (numbers from Delphi 10.1). How that option affects your code depends on your code. During the development of Spring4D I rigorously have used {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}{$ENDIF} in a lot of units to at least reduce any bloat from my code but without recompiling the RTL/VCL/FMX you cannot do that for the Delphi code. -
Why is public class method marked as used, while it's not actually used?
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
A method is a routine (procedure/function) that is associated with an object. A class method would be a routine (procedure/function) that is associated with a class. -
Why is public class method marked as used, while it's not actually used?
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I don't see a class method in that code -
Interesting sort implementation, does not fit into usual API tough
Stefan Glienke replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
@Kas Ob. Not strange at all (maybe a bit misleading UI I admit), what you download there is the source of a specific commit (the lastest master, which would not contain timsort btw, surprise) - repository size includes the entire history. If you want to not use git as intended then you need to switch to the branches tab and there select one of the download options. -
Interesting sort implementation, does not fit into usual API tough
Stefan Glienke replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
@David Heffernan and me implemented one for Spring4D - you can already check it out in the develop branch -
Interesting sort implementation, does not fit into usual API tough
Stefan Glienke replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
Lots of bogus and bias benchmarks -
function reference feature for Delphi source code
Stefan Glienke replied to Nasreddine's topic in GExperts
This feature is called CodeLens - if you fancy you can look on GitHub how its implemented in VSCode. -
Having fun with Delphi
Stefan Glienke replied to Attila Kovacs's topic in Algorithms, Data Structures and Class Design
A string builder must be created and more importantly destroyed. Unless you are making this a custom managed record (which would be equally terrible for fluent API I guess - not tested yet) you would then need to explicitly call some Release/Free/whatever method on that record. If you were to make a fluent API on a record storing all the information those API methods must work with a reference type (such as the pointer to that record) but that makes this API a bit less convenient when you just want to store that result to a variable of that record type (would need an extra call or a deref after the last method call) -
Having fun with Delphi
Stefan Glienke replied to Attila Kovacs's topic in Algorithms, Data Structures and Class Design
Fluent API with records containing managed fields (such as strings) unfortunately produces terrible code because the compiler produces an implicit variable for each method call. -
Is the missing System.TStringHelper SetChars in Chars property on purpose ?
Stefan Glienke replied to Rollo62's topic in RTL and Delphi Object Pascal
I really lol'ed at that one - stockholm syndrome anyone? -
Random unsigned 64 bit integers
Stefan Glienke replied to julkas's topic in Algorithms, Data Structures and Class Design
The description is in the paper and the reference implementation in c is in the very links on that page. Attention though: there is xoroshiro and xoshiro in different variations. -
Random unsigned 64 bit integers
Stefan Glienke replied to julkas's topic in Algorithms, Data Structures and Class Design
Take a look into @Primož Gabrijelčič GpRandomGen.pas -
Does Filter Exceptions make Delphi to steal focus
Stefan Glienke replied to Tommi Prami's topic in GExperts
Why are you running unit tests under the debugger if you are not interested in well actually debugging? If there are any unexpected exceptions the tests will be red and then you select those and start looking into the defects. -
Range checking in library code?
Stefan Glienke replied to Stefan Glienke's topic in Algorithms, Data Structures and Class Design
See my point is this - when a developer writes code like this: for i := 0 to list.Count - 1 do DoSomething(list[i]); it makes absolutely no sense that for every item access to perform the range check. Yes, I know you could use the for-in loop to avoid that but let's just see this as one example of "I have tested this code and I did not make an off by one error on the Count (like forgetting that -1) and let me just get the fastest possible code for my RELEASE build. Unfortunately unless you recompile the RTL/VCL/FMX/you name it yourself you have to stick with pointless sanity checks all over the place. No, I have not done any full application benchmark to actually measure the impact of the overall performance of all types of code that uses RTL lists but I think we can agree that even if the impact might be minor there is one. What I am talking here is the public API of my code that users can interact with and thus I have no control over them passing bad values hence I would like to perform sanity checks to make the code as robust as possible. But I also want the library code to be as fast as possible in a RELEASE configuration (I think this could also stir an argument on whether to turn range/overflow checking on or off then). I certainly don't want to add two levels of API here but make it behave reasonable under DEBUG and RELEASE. I am using these two words for the "tell me when I did a mistake and give me specific information about the mistake" and the "I tested all the code and don't have out of range cases, dont pollute all my code with useless sanity checks" cases. -
Organizing enums
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
And if you would use tinyint you could even save 3 byte per record 😉 -
tbh not having IDEFixPack being available is good in the long run - with the existence of it nobody (or very few) actually cared to report issues and put some pressure on Embarcadero to address these things. Now that there is no solution available the pressure on Embarcadero has raised and I can confirm that they are working on it - will they suddenly implement all fixes and optimizations from Andreas? No, but better they do slowly than relying on the third party no matter how incredible.
-
How to check the zero-based index
Stefan Glienke replied to Marat1961's topic in Algorithms, Data Structures and Class Design
Disclaimer: This is microbenchmark area! Which is why I wrote "sometimes" - but it might be better to write this: if not precondition then raise_some_error; do_stuff into: if precondition then do Stuff else raise_some_error Of course there are other factors - but if we already talk about writing an index check as one instead of two cmp/jxx instructions we might as well talk about that. -
Organizing enums
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
If that would compile - and even if it would that would not prevent that set to be assigned [4] to. -
How to check the zero-based index
Stefan Glienke replied to Marat1961's topic in Algorithms, Data Structures and Class Design
Exactly what I have been doing recently during my refactoring - fun fact: sometimes you even want to rewrite that to avoid the conditional forward jump taken. -
Organizing enums
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
And I thought enums and the possibility to build sets of enums is one of those unique features in Delphi that many other languages such as C++ don't have hence you have to and/or with damn bitmasks.... -
Initialization of returned managed types
Stefan Glienke replied to pyscripter's topic in RTL and Delphi Object Pascal
Use Fixinsight. It catches those. -
Organizing enums
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Give types a meaningful and obvious name. Then you don't have issues remembering them. -
Simple inlined function question
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Those numbers make me assume that you ran in Debug config (i.e. without $O+). -
Simple inlined function question
Stefan Glienke replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Without going into more detailed analysis for now (maybe that's a good topic for a future blog post) I would say even though the older versions produced that extra temp variable and checking against that with the inlined code the main reason why both loops take different durations is due to being in one or two cachelines. We had the same situation some while ago in another thread when we measured different string handling routines. Some performed better or worse and then suddenly a small change changed the result significantly simply because the instructions emitted for the loop were located differently. Some stuff to read about Microbenchmarks: https://engineering.appfolio.com/appfolio-engineering/2019/1/7/microbenchmarks-vs-macrobenchmarks-ie-whats-a-microbenchmark