Scripting in an application
I'm currently exploring the possibility of adding scripting capabilities to one of my applications. This would be a facility where the application user or myself will be able to write scripting code. The script would then be executed in order to alter and/or enhance some part of the hard-coded flow of the application, which is server-based. The application users are fairly competent but are geared towards administration and operations, not serious coding. The goal is to have a way to make quick customizations when the application configuration won't do the job.
The scripting language itself needs to be well-known and not obscure (not home-grown). Dynamic compilation of .Net code is out because I don't want to load additional assemblies in memory. The scripting facility should not shell out to an interpreter - in other words, it should be something that can be hosted inside the application itself. I need basic language constructs (assignments, primitive types, comparisons, if-then, case and loop statements, exception handling, function definition and calling) and some limited but essential database access capabilities. Strong typing is not a requirement.
I'd be interested in hearing from people that may have traveled this road before. What were your requirements? What choices did you consider, what did you choose and why? Most importantly, was the effort worth it?
Re: Scripting in an application
did this once (sort of) before in Vb6... using the VBScript control... we had to allow our users to construct formulas (specialized I might add) ... for which we gave them a grid and using menus and drop downs, they would assemble their formulas from the predetermined data elements... there was no way we were going to allow them free form entry.... anyways... at run time, we would load the formulas from the database, assemble them and add them to the script control... then run it. for what it was, worked fine... uses VBScript, everything is type-less.
If I were to do that again... I'd open it up, allow them to enter in their own stuff, and use the CodeDom to compile it into assemblies. But seeing as how you don't want to go that route.... I don't know... everything I've seen up to now uses the codedom and dynamic compilation in some form.
-tg
Re: Scripting in an application
I take it you weren't too interested in speed of execution but do you have an idea how well did the script control perform in terms of speed? The application's sitting at the server so any script running alongside the code needs to be lightning fast.
Re: Scripting in an application
It was part of an invoicing system... processing anywhere from a few dozen invoices to thousands... so yeah speed was important.... and the script that gets run is rebuilt for each invoice (it implemented tariff logic used to price utility commodities (gas, water, electric)) and in some cases, it could be assembled and run as many as a couple dozen times on a single invoice (multiple accounts, one customer kind of thing). I think it took long to assemble the script then it did to actually run it, and even that was too bad....it involved looping through a recordset and knowing what to do with each record... once the script is assembled and added to the script control, it runs about as good as any vbscript would run I suppose - it's a feature that didn't exist previously, so I don't have anything to compare it to.
-tg
Re: Scripting in an application
There is no such thing as a "VBScript control" but the item referred to may have been the Microsoft Windows Script Control. This is a simple COM wrapper that uses Windows Script engines.
The control is designed to run either the VBScript or JScript engine, and possibly other scripting languages (e.g. Perl) if you install a compatible 3rd party engine.
The program hosting this control can add COM objects to the global namespace of the script or scripts you load. The members of these objects are how the script communicates with and automates various operations of its host.
Both VBScript and JScript are reasonably fast. Example:
Code:
Option Explicit
Private I, J, K, T0
Private Function FormatLong(ByVal Value)
Dim Temp
Temp = CStr(Value)
Do While Len(Temp) > 3
FormatLong = "," & Right(Temp, 3) & FormatLong
Temp = Left(Temp, Len(Temp) - 3)
Loop
FormatLong = Temp & FormatLong
End Function
T0 = Timer()
For I = 1 To 100000
For J = 1 To 100
K = K + 1
Next
Next
WScript.Echo "K = " & FormatLong(K)
WScript.Echo "Took " & CStr(Timer() - T0) & " seconds"
Code:
K = 10,000,000
Took 3.023438 seconds
This sample script outputs via a WScript object supplied by the host. This particular host is a VB6 program meant for use as a WSH IDE, which is why it provides a list of global objects such as WScript to emulate those provided by the CScript and WScript hosts.
There may well be a wrapper for this control or something more direct in the .Net Framework already.
I seem to find a ton of 3rd party embedded scripting tools for .Net too. This would seem to indicate there is no "obvious" route to take in .Net programs.
Re: Scripting in an application
Quote:
Originally Posted by
dilettante
Both VBScript and JScript are reasonably fast. Example:
Code:
Option Explicit
Private I, J, K, T0
Private Function FormatLong(ByVal Value)
Dim Temp
Temp = CStr(Value)
Do While Len(Temp) > 3
FormatLong = "," & Right(Temp, 3) & FormatLong
Temp = Left(Temp, Len(Temp) - 3)
Loop
FormatLong = Temp & FormatLong
End Function
T0 = Timer()
For I = 1 To 100000
For J = 1 To 100
K = K + 1
Next
Next
WScript.Echo "K = " & FormatLong(K)
WScript.Echo "Took " & CStr(Timer() - T0) & " seconds"
Code:
K = 10,000,000
Took 3.023438 seconds
Is that a good enough example to measure performance? Aren't you just looping without doing anything else? You might need to measure a script with more complexity and, more importantly, you may need to know the time it takes to load a script from memory and start the scripting host on it.
Re: Scripting in an application
The script host I was testing with does measure and display the time to load the script as well as to run it. The timing it displayed was only very slightly longer than the script's own measurement (around 20 milliseconds). Of course it's a small script. The Script Control allows you to preload several scripts and invoke them later if you want to shave off some time for each invokation afterward.
Most of what the script code will do is simple "glue logic" doing comparisons and branching and the like. The heavy lifting would be done by calls back into objects within the main compiled program.
I don't think it makes sense to do media transcoding or pixel by pixel image rendering in script, no. Lengthy loops as in my example would be something you'd normally avoid.
The idea behind making an application scriptable is to let the user tie together actions the host program can perform, like a macro language.
However if you have specific benchmarks in mind you can always use an existing generic script host for testing: CScript, WScript, and MSHTA are already avaialble in Windows for this sort of thing. You can also host VBScript within some Office programs. They all use the same scripting engines.
Re: Scripting in an application
Quote:
Originally Posted by
dilettante
However if you have specific benchmarks in mind you can always use an existing generic script host for testing: CScript, WScript, and MSHTA are already avaialble in Windows for this sort of thing. You can also host VBScript within some Office programs. They all use the same scripting engines.
Those were my original thoughts as well. After some googling around, I'm left with the impression that all Microsoft scripting engines are going to be deprecated gradually in favor of powershell. Although powershell can be used with a variety of scripting languages and can also be hosted, my initial tests have shown that it is very slow for my needs, especially when it's being initialized. Just to give you an idea, I'm planning to run a script as part of a financial transaction that now runs at 30ms average in an environment where you can have up to 90 TPS at peak time. I'm shooting for something that will add an additional overhead of up to 25% max.
Re: Scripting in an application
Quote:
Originally Posted by
ntg
After some googling around, I'm left with the impression that all Microsoft scripting engines are going to be deprecated gradually in favor of powershell.
I'm not sure where you're seeing that, but I would expect no less from those heavily vested in PowerShell. I'd rank this rumor somewhere next to those like "the next Windows will be written in .Net" that we hear year after year.
Quote:
Originally Posted by
ntg
Although powershell can be used with a variety of scripting languages and can also be hosted, my initial tests have shown that it is very slow for my needs, especially when it's being initialized.
The PowerShell Runtime can be hosted but this sounds frighteningly inefficient. There must be layers of parsing, translation, code generation and JITting involved in running a script, with tremendous memory consumption. It looks like a dancing bear to me: “The important thing isn't that the bear dances well, rather that the bear dances at all!” All to say .Net can be used for scripting, given a truly horrendous script language syntax to boot.
Quote:
Originally Posted by
ntg
Just to give you an idea, I'm planning to run a script as part of a financial transaction that now runs at 30ms average in an environment where you can have up to 90 TPS at peak time. I'm shooting for something that will add an additional overhead of up to 25% max.
If the target is non-programming users you don't want them writing a lot of script anyway. If they were good at that task they could just write programs to do the job.
The trick in making an application scriptable is to provide the scripting environment with fast, powerful objects and methods. Then their actual script can be little more than glue logic tying these powertools together.
However when you turn something like this over to users they are likely to invalidate the spirit of it and produce mounds of script bypassing the powertools. You see this in things like truly horrendous Access applications that would be better served through a custom application written by an actual programmer. You see it in VB, VB.Net, and C# when people produce mounds of hand-coding to do something the relevant frameworks already offer in a prebuilt component.
But.. If your transactions now take 30ms and you can only tolerate an addtional 25% in making them scriptable I suspect you need to go back to the drawing board.
I just don't see how you're going to accomplish a whole lot in 7.5ms if it has to load and run much of a script at all without processor throughput increased an order of magnitude. Even precompiled .Net or Java are only tolerable because of a decade of Moore's Law in operation, which is why people have to break down and NGen their code to factor out JIT compilation overhead for serious performance.
Re: Scripting in an application
As an example of the inefficiency of script, taking the trivial sample above and pasting it into VB6 and running it I get times reported of:
Compiled to native code with all optimizations on: 0.011 seconds
Compiled to native code with no optimizations: 0.023 seconds
Compiled to p-code: 0.168 seconds
Run in the IDE: 0.238 seconds
Even interpreting the code in the IDE was over 10 times as fast as the script.
Re: Scripting in an application
Quote:
Originally Posted by
dilettante
I'm not sure where you're seeing that, but I would expect no less from those heavily vested in PowerShell. I'd rank this rumor somewhere next to those like "the next Windows will be written in .Net" that we hear year after year.
Well, reading about the various MS scripting hosts, seeing the release time lines and reading about development of Powershell, I do get the impression that it will replace everything.
Quote:
Originally Posted by
dilettante
I just don't see how you're going to accomplish a whole lot in 7.5ms if it has to load and run much of a script at all without processor throughput increased an order of magnitude.
I've done some testing around with a few scripting hosts. It appears that it's a very real possibility to have script execution times that fall bellow 1 ms. SpiderMonkey seems promising but it's quite a task to integrate it into a running application. Jint is routinely integrated in .Net and my initial tests show that it can run a few simple scripts in 1 ms.
As you indicated, a scripting facility can obviously me misused to no end. I'm not concerned with this possibility at the moment.