Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 01/29/19 in Posts

  1. Neutral General

    Rio quality disappoint

    For a while a colleague wrote his code in Notepad++ and copy&pasted it into the Delphi IDE, because Code Insight didn't do anything but randomly make the IDE unusable and unresponsive for up to 30 seconds. He literally couldn't do his work with 10.3. After installing the dev snapshot of the IDE Fixpack it's a lot better now and it's at least usable again. But it's still not acceptable that the IDE is in a state where some people are faster writing code in Notepad than in "RAD" (😂) Studio without disabling themes and a lot of IDE Insight features and having to install a third party patch before being remotely usable. And the worst thing is: a lot of the performance and stability problems exist for nearly a decade at this point
  2. A generic list that doesn't use any heap memory? We show you a couple of ways to create one in our latest blog post! https://blog.grijjy.com/2019/01/25/allocation-free-collections/
  3. Mahdi Safsafi

    Rio quality disappoint

    I didn't install any 3rd party package. My Windows it self had a clean installation and my project was very simple one form and one button (just to test some new things). Also a good IDE should works mostly on all situations and not to work just fine when building a "hello world" project. Recently I compiled the LLVM (which is a very huge project) using MSVS and the IDE handled it very good (just got some CPU overusing ... but that was logical) ! One things to mention about 3rd party : nowadays huge projects split plugins into sub-process (when a plugin fails the main app remains safe) ex: chrome. I'm not saying that EMB should go that way. My point is if a company cares about quality ... it will find a workaround. Please use VSCode, Visual Studio, or eclipse and I'm sure you will change your mind about Delphi IDE quality.
  4. Stefan Glienke

    Allocation-Free Collections

    As I mentioned before the jump optimization highly depends on the CPU - and of course it only affects methods that are being called and not inlined. When inlined you have a jump no matter what. Only when being called it can benefit from two returns in each branch to avoid the jump over. Edit: Clarification - when inlined, putting the raise first is better because it only needs one conditional jump instruction (jump over raise call or not), taken in the common case. When putting it below it still has the conditional jump which is not taken in the common case but has a jump over this code in all cases when the common path is being used. What I would do regardless is to put the exception raising code into a non inlined subroutine to reduce generated binary code because then the code being jumped over is just a call (5bytes on 32bit). Another optimization is to make use of {$POINTERMATH ON} for your pointer type because then you can write: Target := @FData; Target[FCount] := AItem; And another neat trick to check if an Integer index is in range that only uses one compare: if Cardinal(AIndex) >= Cardinal(FCount) then By the way - putting all cases into the same binary often influences results and even the order in which you execute them changes the output - I had a similar case where just changing order made one or another faster or slower. Measuring performance is not as easy at it sounds :)
  5. PeterBelow

    How to create common CreateForm method?

    There is one loophole in your design: if a form is destroyed it will not automatically set the form variable the designer created for it to nil. I can only stress what has been posted in some of the other replies: do not use the form variables for forms that are not autocreated! Delete the variable declaration directly after the form unit has been created by the designer. Use local variables for modal forms (or a class method to create, use, and destroy them). For modeless forms you can always find existing instances by looking at the Screen.Forms array, or have the main form (which presumably creates such a form on an as needed basis) keep the reference in a private field. The automatic form variables encourage some bad programming practices (like accessing controls on another form directly) and become worse than useless if you have to have more than one instance of a given form class open at the same time.
  6. Erik@Grijjy

    Allocation-Free Collections

    You are mostly right about this. If you have a small list size, you are mostly measuring creation/destruction time. But that is exactly one of the reasons you may want to use a stack-based list instead. Although my main motivation wasn't about speed (it was more about memory fragmentation, which is hard to test as you mentioned), I added some speed tests to the repo anyway. Like you said, any speed test in this area is biased, and does not represent a real-life situation, so you should take the results with a grain of salt. I tested 4 stack list implementations against Delphi's TList<Integer>: TStackList1 is the original stack list from example 2 (with a fixed configurable size, but doesn't allow managed types). TStackList2: as TStackList1 but takes Stefan's "put exception at the bottom" suggestion into account. TStackList3: as TStackList2 but uses inlining TStackList4: as TStackList1 but uses inlining I tested these lists with a buffer of 256 bytes on Win32 using Delphi Rio. This shows how much faster each list is compared to Delphi's TList<Integer>. TStackList1: 2.78 times faster TStackList2: 2.77 times faster TStackList3: 2.81 times faster TStackList4: 3.03 times faster Note that measurements vary a bit from session to session. Sometimes, "putting the exception at the bottom" has a positive impact, sometimes it doesn't. TStackList4 is always the fastest on Win32 though, but the differences aren't that big. On Win64, the results are about the same, but Delphi's TList<Integer> seems to perform a little bit better than on Win32. Also, as you said, performance depends a lot on the list size. For a list size of 32 bytes, the stack lists are about 10x faster, but for a list size of 2048 bytes, they are only about 1.7x faster. This reinforces my suggestion that stack lists are most suitable for smaller temporary lists. For larger lists, just stick to heap-based collections instead. And you can tweak the capacity as you mentioned to avoid re-allocations. You can't really test heap usage and fragmentation with these tests. Because we are creating and destroying lists in a loop, a smart memory manager just reuses the same heap memory over and over again without fragmentation. In real-life however, there will be lots of other things going on between the recreation of lists, and fragmentation will be more likely.
  7. Stefan Glienke

    Allocation-Free Collections

    Any pure speed benchmark would be rather useless/biased because it all depends on what you are in fact doing apart from creating the list. If this workload is small enough the object creation would mean a significant overhead. In the end you would just benchmark object creation. Also what affects performance is pointer indirection and memory, CPU cache. In some micro benchmark this would not occur as all memory fits into L2 or even L1 cache. Benchmarking the effect on heap usage/fragmentation is way harder because that cannot be done in pure isolation and usually only manifests in production. FWIW performance for System.Generics.Collections.TList<T>.Add (and other methods) between 10.2 and 10.3 also differs quite significantly (got better). And another thing that sometimes significantly improves performance when adding items to a list is to preset its Capacity to avoid reallocations - in the example given in the blog article with adding 64 integers this already improves performance by 33%.
  8. Stefan Glienke

    Can somebody confirm this in 10.3?

    Yup, did that. To work around that issue, you can put list.List into the watches.
×