Jump to content

Stefan Glienke

Members
  • Content Count

    1365
  • Joined

  • Last visited

  • Days Won

    130

Everything posted by Stefan Glienke

  1. Stefan Glienke

    Possible bug in debugger for Delphi 10.3.1

    Write a visualizer for TListHelper that does not simply show all its fields the standard way but as array. Or simply call its FListObj.ToArray as evaluated expression instead (which would be the dumb version as that causes allocation every time).
  2. Stefan Glienke

    Read of address DEADBEE7. - Source of this raise?

    Correct - it seems to be EurekaLog (see point 3. "When memory is released": https://www.eurekalog.com/help/eurekalog/index.php?memory_leaks_page.php) I would say its that a destroyed TFieldValue was not removed from the list inside the TGridSet - so locate where those are destroyed and check if they are properly removed from that list when in it.
  3. Stefan Glienke

    Possible bug in debugger for Delphi 10.3.1

    They probably should fix this with a debugger visualizer that knows to interpret the FItems field in a TListHelper properly (it also has the fields FCount and FTypeInfo to be able to)
  4. Stefan Glienke

    Spring4D and IEqualityComparer<T>

    No point of injecting the comparer via container. Make a parameterless ctor where you create it. I suggest reading Nick hodges book on DI about the difference of "createables" and "injectables".
  5. Stefan Glienke

    Spring4D and IEqualityComparer<T>

    I meant the implementing class of the comparer or are you using the default from Generics.Defaults? Then just RegisterInstance(TEqualityComparer<whatever>.Default()); Or make an overload without parameter where you create the default comparer and mark that one with [Inject] for the container to use that one because imo a comparer if it does not have dependencies itself falls into the category of a createable thus does not need to be injected.
  6. Stefan Glienke

    Spring4D and IEqualityComparer<T>

    Is that before or after hell freezes over or easter and christmas are on the same day?
  7. Stefan Glienke

    Spring4D and IEqualityComparer<T>

    Does the implementing class itself has dependencies the container should build? Otherwise simply use RegisterInstance. RegisterType with DelegateTo currently does not work although it could let it pass without guid because it then internally does not need it. It's an interesting point though - the fact it needs a GUID is only internally because when creating class instances and resolving them as interface it uses Supports. However since Delphi XE there is some additional type info available for the classes interface table so the container could find the correct one only via the interface type info. I will put that on my list to research to relax that requirement in the future. Oh, how I wish we could use open generics in Delphi ...
  8. Stefan Glienke

    Unused local variables

    Large enough that you don't want to rebuild third party code every time you hit F9+something or waste minutes on the CI server
  9. Stefan Glienke

    Unused local variables

    As Jeroen already mentioned: use DelphiAST - that is based on the Castalia parser code which was based on Martin Waldenburgs code. It is used and maintained by the author of FixInsight and many others and can handle any Delphi code out there. It had a lot of fixes due to it being used in FixInsight which is widely used by numerous people. It even supports inline variables (hello Error Insight!)
  10. Stefan Glienke

    GExperts Grep can use the MAP file

    I am just saying that I dislike having to actually compile the project - maybe I just did a change that causes a compile error which is why I trigger the search ("what unit was this thingy in again...?" or similar). Sure I could have produced the mapfile before I do that change and then let it search it but I have the feeling this will be very inconvenient. Coworker of mine did an IDE plugin for us to automatically propose all the paths that some units referenced in the project are in to add to the search path so I know it's possible (yes, probably a bit more work than simply parsing the map file)
  11. Stefan Glienke

    Unused local variables

    That's why Peter said prebuild - you do that once (and whenever you need to fix some of 3rd party code which is compared to your own code rather rare talking from experience) and then use the produced dcus. That way you only get compiler messages from your code without being mixed with any 3rd party noise. If you work on a large enough application with enough developers that produce builds nonstop rebuilding the same unchanged source code every time is an issue. Especially when Delphi decided that it does not like the "compile" option for whatever reasons and forces you to do "build"
  12. Stefan Glienke

    Check for override

    Funny that you bring up that DevExpress change - I remember upgrading our software and it was a non-issue. And in fact the "what's new" for that version explains exactly what to do. Not saying any of us is right or wrong but you can see that something is a huge issue for one and none for another. Yes, there is always some bad code that did not follow best practices or did not properly encapsulate something, leak an implementation detail or does something else making it a chore to move forward. But that is exactly why I wrote what I wrote 2 posts ago. You can always come up with an excuse (valid or not) to damn some breaking change. However sometimes you have to take the bitter pill to move forward painlessly either yourself or the library/framework developer that decided for such a change. I for example will introduce quite some breaking changes for the next version of Spring4D and I experienced them myself when migrating a branch of our software to an early version and experienced all the required work. I even reverted some change because I saw that it was rather painful to find all the places and convert them easily. That means as a developer of a component/library/framework you should use that yourself in more than a toy project to get a feeling what consequences possible changes have to evaluate if they should be taken or not. And it then is an important responsibility to document them and if necessary provide some tooling to migrate your code - I remember more than 10 years ago when moving from QuantumGrid 3 to 4 (I think) DevExpress provided a tool to convert all your code for that heavy breaking changes that came with that version change. If they would not have done that, I guess no existing customer would have done it - however I cannot tell about the problems that still existed, I joined the company when the change was done already.
  13. Stefan Glienke

    Check for override

    For once I have to wholeheartedly agree with Rudy - I have to mark that on my calendar.
  14. Stefan Glienke

    GExperts Grep can use the MAP file

    Fair enough - I would have used a different approach though that does not involve having to compile the project by recursively collecting all used units by analyzing their uses clause.
  15. Stefan Glienke

    GExperts Grep can use the MAP file

    Please explain - what does the map file have to to with finding out units that are included in the project via search path? It would have to parse the uses clauses and then look for those files in the search path directories - figuring out if a unit is actually being used because the compiler might find a dcu instead is left as in improvement.
  16. Stefan Glienke

    Check for override

    I am not going to search through JIRA right now but JSON Serialization and the years of aftershocks of Generics.Collections refactoring come to mind. Or negative performance impact through changes in System.pas routines because of some feature that I might not even use (I remember some occasion where some dynamic array handling routine suddenly got severely slower) I am not using FireMonkey myself but I know there were numerous of breaking changes - for the better probably but there it obviously was not such a problem to let the users bite the bullet and adapt. Then some useful features in the IDE got missing during the theming rework (like additional context menu items in the editor tabs like open in explorer or showing the save state of those units) Can probably find more examples by searching for "regression" in JIRA. This is just a general overview of my feelings I have with every new version - crossing fingers nothing important broke. And this should not be.
  17. Stefan Glienke

    Check for override

    I did exactly that. And that is why I wrote "a clear guide at hand how to solve it" - breaking changes without a migration guide are bad. I have seen many occasions where Borgearcadera justified not fixing bugs with "backwards compatibility" to keep broken code working and push the need to keep writing code in a broken way (design wise or literally) or added ridiculous workarounds into the code to fix something but without the necessity for anyone to fix their code - and I am not talking about subtle and hard to track things. But then on the other hand break things every other version just because...
  18. Stefan Glienke

    Check for override

    "Backwards compatibility" is the ultimate excuse to pile up garbage in your backyard ... It is used or ignored whenever convenient - moving forward also includes getting a compile error in your face but with a clear guide at hand how to solve it. If you ever inherited from a TDataSet and used one of its method that have TBookmark or TRecordBuffer arguments while writing code for different Delphi versions since 2010 or so you know what I mean. But some developers seem to rather want to save an hour when moving their code to a new version and waste hours or days later hunting down a bug. 😉
  19. Stefan Glienke

    Check for override

    If the method you avoid to call would do heavy work... but even using the fastest approach to check if the method is overridden will be slower than just doing a virtual call on a method that just returns False. And even if you perform that check only once and store it in a boolean field it's just not worth it imo.
  20. Stefan Glienke

    Check for override

    IsVirtualMethodOverride from Spring.VirtualClass.pas procedure TAncestor.Do; begin Writeln(IsVirtualMethodOverride(TAncestor, ClassType, @TAncestor.MethodX)); end;
  21. Stefan Glienke

    Rapid generics

    All this drivel that happens every time when David and Rudy collide is rather annoying to me and totally went off topic long ago. But that's what you can ignore content for. I would appreciate if you as a mod would cut that out and move it to it's own thread.
  22. Stefan Glienke

    Rapid generics

    But we have the slow RTL routines that can easily be improved - we don't have the new ctors and dtors and actually I would not hold my breath for them to be implemented as you imagine them to - they will be driven by additional typeinfo (look into 10.3 System.pas where you can find all the relevant code for that feature because they just disabled it inside the compiler but did not revert the necessary RTL code). And still if you have an array of those record it would still have to loop through the array and call the dtor for every single item regardless. An optimized version of FinalizeArray/Record can just shift pointers over the array and do the cleanup - even if using the records managed field table - that is just a simple record structure, nothing fancy. Putting everything into nested loops and calls regardless the fact if the fields are even filled with something is what makes the current version slow - that is as I mentioned before what makes Rapid.Generics faster on its Clear.
  23. Stefan Glienke

    Rapid generics

    Write a better _FinalizeArray routine for tkRecord then please as the current implementation is pretty terrible as it keeps calling _FinalizeRecord in a loop which again calls _FinalizeArray with ElemCount 1. That contributes to the slowness of Generics.Collections if you have records in a list. I did some patching today and added an ElemCount parameter to _FinalizeRecord to only call that once per _FinalizeArray - but did that in pure pascal.
  24. Stefan Glienke

    Rapid generics

    Storing records in collections is a delicate topic as usually the code is a bit more complex than just storing integers or pointers. Even more so if the record has managed types like string. In this case the simple fact of having a local variable of T inside your generic code and doing one assignment more than necessary (because for example passing some olditem to a notification) might cause a severe slow-down. If you put such code into a single method it does the stack cleanup and finalization for that variable in all cases even if there is no notification to be called. The code in Rapid.Generics is using some shortcuts and produces even more convoluted code than System.Generics.Collections has since its refactoring in XE7. It does for example not use TArray<T> as backing storage for its list but pure pointer math. It also does not zero memory for this array which buys some speed by not doing the round trip to those all the code happening in System.DynArraySetLength - especially for managed types. That buys a bit of performance when adding items - especially if you don't set the capacity before. I know that the RTL collections had a ton of bugs caused by that refactoring as certain typekinds suddenly were not handled properly - I don't see any unit tests for Rapid.Generics though so I would not say that they are working for all kinds of types that you might store in those lists. As for the specific case of Clear taking longer in the RTL collections that is another optimization being done in Rapid.Generics where it simply cleans up the memory and is done whereas the RTL runs through some extra code which is not necessary if there is no OnChange attached to the list. Edit: I looked into the Rapid.Generics code for records and it maintains its own mechanism to cleanup any managed fields with a small performance improvement if the field is actually empty. This causes a major speedup if you are doing some benchmarks with empty records but I guess with real data this won't give much. I tested with a small record with 2 string fields and an integer and when they were empty the Clear call was very fast compared to the RTL list but not so much anymore when the fields contaied some strings that it had to cleanup.
  25. Stefan Glienke

    Rapid generics

    Well this still does not tell anything about how the list is being used, What their element type is or if they have a change notification attached (because all that influences the performance). I am asking because I have been spending quite some time looking into the rapid.generics code and the 10.3 system.generics.collections improvements and did some own for spring4d. And what makes testing with isolated (micro)benchmarks kinda difficult is the fact that often enough the hardware effect kicks in and shows you big differences that are just there in this benchmark but in real code completely irrelevant or even contradictory.
×