DWS news roundup

Here is a quick summary of recent additions to DWScript:

  • exit, break and continue are now reserved keyword (and highlighted as such), previously they weren’t (as in Delphi), but having variables or functions named that way just “breaks” (pun intended) those language features (as it does in Delphi)
  • new TdwsRTTIEnvironment, fields and properties of a class exposed this way are directly accessible in scripts, more details on that one in a future post.
  • support passing constant arrays to dynamic array parameters (automatic conversion).
  • improved the language documentation.
  • added ability for custom extension of Abs() special function (now supported by TComplex).
  • added Clamp() floating-point function.
  • added Gcd(), Lcm(), IsPrime() and LeastFactor() integer functions.
  • fixed an issue that prevented conditional directives from being supported in all portions of the code, they can now properly be used anywhere.
  • JavaScript codegen optimization for variable symbol lookup.
  • minor tokenizer speedup, compile speed should now be close to 200k LOC/sec*.
  • more test cases, minor fixes.

*: FWIW since the old benchmark, compile and execution performance almost tripled and memory requirements were cut by approx 30%. At the same time the language became quite a bit richer.

8 thoughts on “DWS news roundup

  1. Is there a way of “saving” a script state with minimal memory use?
    I’m thinking about server-side workflow handling using DWS. The same workflow script could be launched once per client, then executed step by step depending on the client behavior.
    The expected feature could be to “share” the same script tree to all clients, to minimize memory use.
    Is it possible with DWS?

  2. @A. Bouchez
    A single compiled program can have multiple executions, which will only use memory for their stack/heap. A particular execution can be run multiple time, or have the functions/classes it exposes be executed multiple time in any order, as long as the calls are serialized.

    You can’t “persist” a script, but you can “keep” a compiled program and its execution(s) in memory for multiple reuses. The constraint is that a particular execution should be used from only one thread at a time, but it’s not tied to a particular thread (unless the Delphi objects you use through that script have other limitations, of course).

  3. @Eric thanks for your answer.
    Therefore, I can “re-use” an existing script (just as an executable can be run more than once), but I can not share the same script instance between multiple instances.
    I would need DWS to handle multiple workflows at once (think about handling a basket for a commercial web site). Instead of creating a state machine, I was tempted to implement it in DWS. A single script would be running on the server for each connected client, handling the whole process.
    I know that you made a lot of efforts about keeping memory use low. But I was thinking about sharing an AST, just like you share the DWS RTL units to speed-up compilation. Is it not possible with custom scripts?
    Is there a way of “cloning” an existing compiled program? I.e. copy the AST to avoid parsing and compiling for each script instance?

  4. but I can not share the same script instance between multiple instances.

    Depends on what you mean by “instance”, if your server is having multiple instances of an executable running at the same time then no, but if that’s the case, you should be able to run a single instance of that executable and take advantage of multi-threading rather than multi-processing, in which case it would work, and you would save some memory and performance.

    A single script would be running on the server for each connected client, handling the whole process.

    If the script is the same, you can have one compiled program, with multiple simultaneous executions, in which case the memory usage per client would be that of the execution stack and that of whatever classes you would instantiate.
    If you make your script objects persistent, and have your code implemented as methods of that object, then you could persist that too.

    I know that you made a lot of efforts about keeping memory use low. But I was thinking about sharing an AST, just like you share the DWS RTL units to speed-up compilation. Is it not possible with custom scripts?

    I’m not sure to follow, you mean that each client would have a different script, but with some common units and you want to share the common units only but not the client-specific scripts?
    By default executions share the same expression tree, the mechanism for the DWS RTL serves a different purpose, and extending it would matter only if each client would use a different, per-client script, with a bunch of shared code. This is currently limited since safely supporting it in the general case would require some extra structures which don’t exist yet.

    Is there a way of “cloning” an existing compiled program? I.e. copy the AST to avoid parsing and compiling for each script instance?

    No, you can’t clone the expression tree, but since the compiled scripts can be shared by multiple instances, unless all your scripts are both unique and large, it shouldn’t matter: you can just “cache” the compiled programs for all your scripts and reuse those for as many execution instances as necessary.

  5. @Eric Thanks again for taking your time to clarify it.
    In fact, I made a confusion between the AST and the execution stack.
    What I would need is to have multiple execution stack (handled in a pool) of the same compiled program.
    I think this will be a fine way of implementing my workflows on the server.
    The same script is to be executed by multiple clients. So I’d have an unique compiled program, with several execution stacks, managing all clients instances. An execution pool would be implemented to re-use a previous execution stack, when a client has finished to use its SOA interface instance.
    I think this will be much more elegant than the GUI-driven implementation of Workflow in .Net – see http://msdn.microsoft.com/en-us/netframework/aa663328.aspx
    My intention is to have AJAX client using DWS (using certainly OP4JS classes), then an interface-driven Workflow service provider using DWS. Therefore, our Client-Server ORM will have consistent use of its objects, and would be able to share a lot of object pascal code at all layer of its Domain-Driven architecture. Some business logic would be able to be tuned at runtime in DWS workflows, whereas the main executable and core business logic would remain hard-coded in the Server executable.

  6. @A. Bouchez

    What I would need is to have multiple execution stack (handled in a pool) of the same compiled program.

    That is supported.

    An execution pool would be implemented to re-use a previous execution stack, when a client has finished to use its SOA interface instance.

    The execution object (TdwsProgramExecution) is quite light, so there may not be much practical gains form using a pool, unless your scripts are very simple ones.

Comments are closed.