Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 02/17/20 in all areas

  1. @Tommi Prami I guess you found out about Lemire in our latest commits - see e.g. https://github.com/synopse/mORMot/commit/a91dfbe2e63761d724adef0703140e717f5b2f00 🙂 @Stefan Glienke It is to be used with a prime size - as with our code - which also reduces memory consumption since power of 2 tables are far from optimal in this regard (doubling the slot numbers can become problematic). With a prime, it actually enhances the distribution, even with a weak hash function, especially in respect to anding a power of 2. Lemire reduction is as fast as anding a power of 2 since a multiplication is done in 1 cycle on modern CPUs. Note that Delphi Win32 is not so good at compiling 64-bit multiplcation as involved with Lemire's, whereas FPC has no problem using the i386 mul opcode - which already gives 64-bit results.
  2. Alexander Sviridenkov

    JFF: FMX + FR + HTML

    Yes, platform and framework doesn't matter, VCL, FMX, iOS, Linux, etc.
  3. @David Heffernan Yes, the fastest heap is the one not used - I tend to allocate a lot of temporary small buffers (e.g. for number to text conversion) from the stack instead of using a temporary string. See http://blog.synopse.info/post/2011/05/20/How-to-write-fast-multi-thread-Delphi-applications
  4. As Dalija said: Raising exceptions in the constructor is possible and even normal (e.g. TFileStream.Create for a file that does not exist or maybe is only temporarily not available). It's documented that the destructor must handle partly constructed objects. Allen Bauer blogged about this in 2006 (aparently he has removed his About Me page from the blog, or did it never have one?) But yes, many Delphi developers are not aware of this. I only recently (as in "a few years, maybe a decade ago") became aware of this issue and am still finding code that does not take this into account.
  5. This kind of descriptions are priceless for any unit that is something more than a set of various utilities. The same for quick overview of some classes. Sadly those who write such descriptions are very rare 😞
  6. Alexander Sviridenkov

    JFF: FMX + FR + HTML

    You can use SVG images defined via href, standard FR DB fields (as shown in video) which may contains HTML too, or load complete HTML using http or other protocol, but last one requires overriding one component method.
  7. The capacity implementation of the RTL dictionary is a bit stupid. Typically the capacity is the number of items you can store in a collection without a reallocation/grow happening. However that is not the case here (in Spring4D we actually implemented it that way - so if you want to store 100 items without a grow happening you pass capacity 100 - the internal mechanism handles overallocating to satisfy the max fill factor). The RTL implementation takes the passed value, calculates the next power of 2 greater than the passed value, allocates as many buckets and sets the grow threshold to 75% of that value. In the benchmark code above that means from the passed 200 it calculates 256 and sets the threshold to 192 which means you can store 192 items before it will grow.
  8. var Strings: TStringList; begin Strings := TStringList.Create; try Strings.LoadFromFile('C:\SomehugeFile.txt'); finally Strings.Free; end; end; Above is trivial example that can easily cause OOM error and it is also simple to handle and fully recoverable. You can easily wrap the whole thing with try...except block, show message to the user and application can merrily go on like nothing happened. We disagree then. Maybe my imagination is at fault, but I have really hard time imagining how would solution with non-throwing constructors be simpler to handle and make code less complex and convoluted.
  9. Actually especially for a hashtable that algo is really terrible. It makes it super vulnerable against a non optimal hash function or heavy occurency of hash/bucket collisions. Mod or anding with capacity-1 provides a better distribution.
  10. Every instance construction can fail because of out of memory error. But there is nothing special in surviving such exception. It only depends what you are doing at that time. Whether it will be recoverable error or not depends on the developer. Also throwing exceptions during construction is not a trap... Delphi has mechanisms in place that allow full cleanup and recovery. That is all that matters. If we didn't have exception throwing construction, we would still have to deal with all kind of "exceptional" situations where you would have to be prepared for handling them. And it would not be any simpler than what we have now. Basic problem in this particular case is non trivial ownership transfer, not the exception throwing constructors per-se. Solving ownership transfer solves the problem. Moving construction of dependent class to within owning class eliminates ownership transfer and solves core issue. (Another approach would be using reference counted classes and automatic memory management)
  11. Construction the instance in outer scope is indeed the problem here, but your code still constructs the instance in outer scope. In order to prevent all leaks, instance must be constructed from within the constructor because exception could be raised before constructor chain is called. In such case you still leak TSomeOtherClass instance.
  12. What about the theory that dictionaries have fewer collisions if you set the capacity to be a prime number ? Fact or fiction? Personally, I do actually set the capacity to a prime, but I am not quite sure if it because it is sound advice or if it is a cargo cult thing. Edit: Funny enough, @Tommi Prami posted an alternative approach.
  13. Just a note to your article TStringList vs. THashedStringList vs. TDictionary: In Delphi 10.3.3 THashedStringLIst is not used to speed up TMemInifile anymore. AFAIK it is not used anywhere in the standard libraries and probably only there to stay compatible. Btw, I agree that it is poorly implemented.
  14. Not so simple. For small collections the dictionary can be slower.
  15. I don't agree with that. A good coder can express something in 5 lines what a poor coder takes 25 lines to say. And the poor coder might not be able to make heads or tails of the 5-line version. And six months after writing the 5-line version, the author might not even recognize it! Code you write "now" is ALWAYS "self-explanatory". That's not why one writes comments -- you don't need them in 5 minutes ... you damn well might need them in 5 months, however! I'm going through a bunch of code right now for the first time, and even though the names of things are quite long and the code is well-organized, there are no comments anywhere, and it's really challenging trying to figure out what's going on. Actually, I take that back ... there are some /// comments above some classes and methods in the interface section intended to be used to create some rough documentation. What's missing is any sort of "big picture" explanation other than one method near the bottom that calls 15 different things declared above it, and none of them pass any parameters, yet they seem to be working on several "global" vars (in the class) that are then revised and refined and used among the methods. Well ... some are, some aren't. Being an "expert" sometimes means knowing that "if it ain't broke, don't fix it" applies. Refactoring increases the risk of breaking things that have invisible side-effects. If there are no unit tests, then it's a crap-shoot. I like to put "big picture" comments at the top of units, but I'm frequently criticized for it. They're as much for my benefit as others. I worked at a place once where a colleague would put needless comments like "getter" and "setter" next to the read and write parts of property statements (on 3 lines) and delete comments where I was explaining parameters on procedure and functions. Makes you scratch your head sometimes.
  16. Yes, but it comes with the Delphi installation and thus doesn't need to be maintained externally. I also have customers avoiding additional libraries. Each new one has to be justified to someone, which often turns out to be a tedious process. Not everyone has the power to decide on its own.
  17. Stefan Glienke

    array of weak references

    Nope, that would be an array of unsafe references - an important characteristic of a weak reference is that it will be cleared when the referenced instance gets destroyed. Since you cannot declare TArray<[weak]IInterface> or something like that you need to make a record type with a weak reference field. Since Object ARC will be history with 10.4 I don't care - but weak reference for interfaces will still be a thing: {$APPTYPE CONSOLE} uses System.SysUtils; type weakref = record [weak] ref: IInterface; class operator Implicit(const value: IInterface): weakref; inline; class operator Implicit(const value: weakref): IInterface; end; class operator weakref.Implicit(const value: IInterface): weakref; begin Result.ref := value; end; class operator weakref.Implicit(const value: weakref): IInterface; begin Result := value.ref; end; procedure Test; var refs: TArray<IInterface>; weaks: Tarray<weakref>; intf: IInterface; begin SetLength(refs, 3); refs[0] := TInterfacedObject.Create; refs[1] := TInterfacedObject.Create; refs[2] := TInterfacedObject.Create; SetLength(weaks, 3); weaks[0] := refs[0]; weaks[1] := refs[1]; weaks[2] := refs[2]; refs := nil; Writeln(Assigned(IInterface(weaks[0]))); Writeln(Assigned(IInterface(weaks[1]))); Writeln(Assigned(IInterface(weaks[2]))); end; begin Test; end. FWIW Spring4D has Weak<T> that works for interfaces and objects and has the added feature that when used for objects on non ARC platform it also clears then and thus protects against dangling references.
  18. David Heffernan

    Spell Checker implementation?

    http://hunspell.github.io/
  19. Uwe Raabe

    Tool to fix up uses clause unit namespaces?

    I have written a tool including that functionality some time ago. Although I didn't find the time to polish it up before going public, it basically does what it is supposed to. Expanding unit scope names is only part of the whole process, which consists of resolve all unit aliases expand unit scope names group units compress uses clause Taking your example above it will convert uses sysutils, stdctrls; into uses System.SysUtils, Vcl.StdCtrls; Feel free to adjust the sources to your needs. UsesCleanerSource.zip
×