Jump to content

Arnaud Bouchez

Members
  • Content Count

    325
  • Joined

  • Last visited

  • Days Won

    25

Posts posted by Arnaud Bouchez


  1. RTC is a great set of communication classes.

    kbmMW and mORMot are not only communication layers, but full toolboxes, with plenty of other features. They have very diverse philosophy/design.

    You may also take a look at the TMS components.

     

    One big difference is that mORMot is fully Open Source, is used in several critical projects so is highly maintained, and works fine with FPC on a variety of platforms - we use it on production Linux x86_64 servers to handle TB of data from thousands of clients.
    The fact that mORMot SOA can use interfaces to define the services, and WebSockets for real-time callbacks from server to client, make it unique.
    There is a full refactoring called mORMot2 which should be finished next october (I hope).


  2. 22 hours ago, Kas Ob. said:

    So i would suggest another page above documentation and installation and below the main page on GitHub, to show samples, the shortest samples for specific functionality starting with HTTP GET ( secure and unsecure), to the most advanced topic like microservices and IPC.

    Fair remark.

    This was the point of the FAQ:

    https://synopse.info/files/html/Synopse mORMot Framework SAD 1.18.html#TITL_123

     

    Also check https://tamingthemormot.wordpress.com/ blog entries.


  3.  

    1 hour ago, Clément said:

    I wrote a Windows Service (REST HTTP Server) does a lot of stuff 😎. Several users (hopefully) will be connected and each might need to call this "app" from their own thread.

    Well, I would like to avoid compiling those modules into the main Service, because they will get changed a lot more often than the service itself.  Some modules are specific to some users.

    I am confused by this description. What do you call a "user"? Is it a client app? Then why this client logic should be compiled within the main module?

    Please refine your system description.

     

    If you meant having your main service call some sub-functions for custom process, then you may rather call separated services.
    An embedded dll (or com server, whatever) is the right way to make your system instable. If the dll has some memory leaks or write somewhere in memory, you may corrupt the main process....
    So I would isolate the custom logic into one or several dedicated services - so point 3.

     

    Perhaps you need to refine the design of your SOA solution. You don't need a monolithic REST server. The best practice today for several services is to create MicroServices.

    When a Windows Service "does a lot of stuff", from my point of view it sounds like not a very maintainable design.

    The first step would be to split the main service into smaller services, then put an orchestrator/application service as frontend, calling third-party services if necessary.

    Perhaps some design part of our framework documentation may help. Check http://mormot.net


  4. Try to push a pull request to the original project, if it is Open Source.
    If it is useful to you, it may be useful to others.
    The pull request may not be directly merged, since the project owners may have some requirements (testing, code format, comments, documentation, cross-platform...).

    It is a great way to enhance your abilities, and give back to the community.

     

    For 3rd party non-free components, it is more difficult.
    You may use the branch feature of a SCM (git or fossil e.g.) to backport the original 3rd pary code updates to your patched branch.

    • Like 1

  5. Old versions of FPC, sadly.

    Gareth did some optimizations included in 3.2 and trunk... worth seeing it live in the generated asm!

    I have seen generated asm being improved in FPC since years. I sadly can't say the same with Delphi - especially on cross-platform, e.g. about inlining floating point operations.

     

    I use godbolt since years to check the asm generated by latest gcc with high-level of optimization and opcodes.
    It is useful to have some reference code when writing some SSE2 or AVX/AVX2 asm.

    • Like 2

  6. Side note: see for instance the ProtectMethod use of https://synopse.info/files/html/Synopse mORMot Framework SAD 1.18.html#TITLE_57 which is similar.

     

    What I miss with records is inheritance.
    Static inheritance, I mean, not virtual inheritance.

    This is why I always like the `object` type, and find it weird that is deprecated and buggy since Delphi 2010...

    Check https://blog.synopse.info/?post/2013/10/09/Good-old-object-is-not-to-be-deprecated-it-is-the-future almost seven years ago... already...

     

    I tend to search for alternatives not in C++, where alternate memory models were added later on - as with Delphi.
    But in new languages like Rust which has a new built-in memory model. Rust memory management is perhaps the most interesting/tricky/difficult/powerful/promising (pickup your own set) feature of this language.

    Both C++ and Delphi suffer from the complexity of all their memory model. COW, TComponent, interface, variant, new/dispose, getmem/freemem, create/free... it may be confusing for newcomers. My guess is that 80% of Delphi RAD users seldom allocate manually memory (just for a few TStringList), and rely on the TComponent ownership and visual design.
    At least they removed ARC from the landscape! 🙂

     

    CMR is a nice addition - which FPC featured since some time, by the way...
    We still need to check the performance impact of this initial release - writing efficient RTL was not the main point of Embarcadero these latest years. I hope it won't reduce regular record/class performance. 

    • Like 2

  7. It is not obvious to me what is the advantage in respect to using an interface-based (or custom variant-base) instance holder.
    You can auto-generate the same try/finally hosting the data within an interface, or a custom variant. Since the oldest Delphi revisions.

    Interfaces can host regular objects with no problem. A custom record may be slightly faster, by allocating its memory on stack and not on heap - but performance is not the main point here, this is about code writability - less source lines, more hidden behavior.

     


  8. 54 minutes ago, David Heffernan said:

    You don't get this because the return type is a managed type and so is actually passed as an extra var parameter.

    Indeed. I would have written an "out" parameter in the docs, at least. The function should set or initialize the value.

    And the compiler should emit a warning in your case.
    FPC is much more paranoid about such warnings, but at least it tries to warn anything dubious, and allow to disable false positives with the {$H-} trick on the faulty line.

    • Like 1

  9. I never install the Delphi 2007 IDE any more. I just copy the dcc.exe and some files (including its dcu) and use the command-line compiler. 
    For testing, it was enough... and nothing to setup, just copy the files from an existing setup.

     

    Edit: But I understand now it won't help you, since I guess you need to validate installation of your IDE plug-in.

    Sorry.


  10. 17 hours ago, Stefan Glienke said:

    However - unless you write core libraries like Arnaud or me you usually don't care.

    This is the main point.

    Premature optimization is the root of all evil! 🙂

     

    @Mahdi Safsafi  Such abstract/broad input about non Delphi compilers has nothing to do with the initial question of this thread, which is performance of string process with Delphi. It is clearly out of scope and subject.
    What does a DSP compiler has in common with the Delphi compiler? Even the MAC units of DSPs have very little in common with regular CPUs.


  11. @Mahdi Safsafi

    My experiment with the Delphi compiler and pointers is not the same as yours. In mORMot, I ended up with using pointers (PUTF8Char=^AnsiChar) for the raw UTF-8 processing, which generated faster code.

    Of course, pointers are difficult to deal with - you need to know what you are doing.

    I always consider pointers by looking at the generated ASM. If the code is better and runs faster with pointer, then I use them. Otherwise I don't.

     

    I am biased for sure: I like pascal because it can be both high-level and modern (like Java/C# - with high-level structures like classes, strings or dynamic arrays), and also system-level (like C). Pointers are clearly for the 2nd level.
    Anyone don't like pointers? Don't use them. But they are pretty convenient and efficient for low-level processing, if the goal is performance.

     

    I like very much when you paternize me with the Gather-scatter pattern. You can perfectly do Gather-scatter with two pointers. This is called pointer arithmetic - which I use extensively in mORMot. So I don't understand what you are talking about.

    • Like 1

  12. 13 hours ago, David Heffernan said:

    It's pretty unlikely to encounter this issue in real code. 

    It occurred to Eric at least with DWS. He actually monitored it before fixing it.
    Of course, he dealt with a language compiler and execution stack, but I guess a lot of other kind of projects may have very tiny objects - if the SOLID principles are properly followed.


  13. 20 hours ago, Mahdi Safsafi said:

    As I mentioned before, Compiler is much able to understand integer behavior over pointer behavior. CPU can also be smart to prefetch next data for you on the background.

    This is not as simple as this. IIRC prefecthing has no difference between indexed (mov ecx, byte ptr [eax+edx]) or direct access (mov ecx, byte ptr[eax]).

    The reference material about instruction latency and execution pipelinging is https://www.agner.org/optimize/instruction_tables.pdf and it is highly depending on the CPU.

    https://www.agner.org/optimize is worth reading and understanding.

     

    https://lemire.me/blog/ is another very interesting blog about performance of text processing, from a lot of experience and actual knowledge.

    Branchless SSE code will be the faster in all circumstances...


    Then use a wall clock measure of full realistic process - not just measuring a loop.

     

    • Like 1

  14. 20 hours ago, Stefan Glienke said:

    @Mahdi Safsafi I just found recently that using a for-to loop with indexing into a pointer was faster than inc(thatpointer).

    It depends on the complexity of the loop.
    For instance, about how variables are assigned to local stack variables or registers. If the use of the for-to index is not mapped into a register, then thatpointer[ i ] will be slower...
    Sometimes, just using a small local functions help the Delphi compiler make better register allocation, and may end up be faster...

     

    Remember 

     🙂

    • Thanks 1

  15. On 7/18/2020 at 3:18 AM, Mahdi Safsafi said:

    Yeah Stefan, I clearly understand you. But the same thing you described can be achieved by branch prediction. So compiler should not generate such code unless you are targeting an old cpu. 

    Branch prediction can do wonders in some micro-benchmarks, but they always have a cost, until the CPU logic actually "warmed up". No branch is always better, since the real problem is branch misprediction.

    Using the asm generated by a recent GCC with tuned optimization flags as a reference is a good hint of what is likely to be more efficient. Intel and AMD are major GCC contributors.
    And a wall clock of a realistic process (not micro benchmark) is the ultimate reference. We use some part of our automated tests as performance benchmark, running some close-to-the reality scenarios.

    • Like 1
×