Halfway through the week I realised that I might have overreached myself just a little by promising to deliver the future and then most of the fun I had this week was still to come.
So, I'll postphone the future to next week and give you a short troubleshooting tip this week. For sometimes things go wrong. Networks can flap, disks can fail, processors can overheat. And then there's the OS, the JVM, ... Sometimes it is just amazing that anything works at all.
There is of course the Status tab in the HTTPBackend Fulcrum that has live graphs to study, but there is also the Requests and Threads page in the Developer tab.
Now this is a static page and I needed the information on just one specific thread at a more frequent interval. So I wrote a new tool :
<mapper>
<config>
<endpoint>
<grammar>res:/tools/kerneldetail/
<group name="threadname">
<regex type="anything"/>
</group>
</grammar>
<request>
<identifier>active:xslt</identifier>
<argument name="operand">netkernel:/k</argument>
<argument name="operator">res:/resources/stylesheets/kerneldetail.xsl</argument>
<argument name="threadname" method="as-string">arg:threadname</argument>
</request>
</endpoint>
</config>
<space>
<fileset>
<regex>res:/resources/stylesheets/.*</regex>
</fileset>
<import>
<uri>urn:org:netkernel:xml:core</uri>
<private/>
</import>
<import>
<uri>urn:org:netkernel:ext:system</uri>
<private/>
</import>
</space>
</mapper>
Did I say write ? No code (after no sql it is now time for the new paradigm, no code) of course. The netkernel:/k resource provides the raw data and I filter that with xslt :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nk="http://netkernel.org"
version="1.0">
<xsl:output method="xml"
indent="yes"
encoding="UTF-8"
omit-xml-declaration="yes"/>
<xsl:param name="threadname" nk:class="java.lang.String" />
<xsl:template match="/k">
<xsl:copy-of select="threads/thread[name=$threadname]"/>
</xsl:template>
</xsl:stylesheet>
And that's it. Put in a small script ... for example like this :
#!/bin/sh
while true
do
curl http://localhost:1060/tools/kerneldetail/ConcurrentCacheCullThread >> /var/tmp/culler.out
sleep 10
done
And collect all the data you want with minimum system impact.
So, next week I will deliver the future as promised.
2012/03/23
2012/03/16
space listing
I remember being disappointed when I learned that an asteroid belt is nothing like what I knew from videogames (also an excellent song by Lana Del Rey), where you have to maneuver your ship between rocks with hardly any space between them. The truth is that you can pass through an asteroid belt without even seeing or coming close to any asteroid at all!
Space is like that. Contains a near infinite number of things but if you don't know where to look it might as well be empty.
Spaces in ROC (because of the way I set up your mind you might read that as "rocks in space") can also be like that. Sometimes you just want to know what is there before you go in and request it.
Note that this is not a logical train of thought. Because - and I quote Peter Rodgers - how do you enumerate a potentially infinite set?
It is however a practical train of thought, one that can only be followed through for spaces that are enumerable (whatever that means for the given space type). Such as a fileset. And of course, there's a tool in NetKernel that allows you to do that. Try the following in the Scripting Playpen :
Space is like that. Contains a near infinite number of things but if you don't know where to look it might as well be empty.
Spaces in ROC (because of the way I set up your mind you might read that as "rocks in space") can also be like that. Sometimes you just want to know what is there before you go in and request it.
Note that this is not a logical train of thought. Because - and I quote Peter Rodgers - how do you enumerate a potentially infinite set?
It is however a practical train of thought, one that can only be followed through for spaces that are enumerable (whatever that means for the given space type). Such as a fileset. And of course, there's a tool in NetKernel that allows you to do that. Try the following in the Scripting Playpen :
<sequence>
<request assignment="response">
<identifier>active:sls</identifier>
<argument name="space">urn:org:netkernel:ext:system</argument>
</request>
</sequence>
Here's a snippet of the result :
Here's a snippet of the result :
<dir id="res:/etc/" name="etc">
<res id="res:/etc/messages.properties" name="messages.properties"/>
<dir id="res:/etc/system/" name="system">
<res id="res:/etc/system/Books.xml" name="Books.xml"/>
<res id="res:/etc/system/Docs.xml" name="Docs.xml"/>
</dir>
</dir>
Now we are getting somewhere! This opens up possibilities for a resource oriented ftp server or a resource oriented content management system or a <your idea here>.
When you read the documentation for sls you'll notice that there are plans for some future enhancements. Come and see the future in next week's entry!
Now we are getting somewhere! This opens up possibilities for a resource oriented ftp server or a resource oriented content management system or a <your idea here>.
When you read the documentation for sls you'll notice that there are plans for some future enhancements. Come and see the future in next week's entry!
2012/03/09
What did you expect ?
One of these days Peter Rodgers is bound to mention in the NetKernel Newsletter that I repeat/rehash a lot of what he and Tony have been saying all along. Of course I do. What did you expect ?
I want to focus on that question today. For in these days of multi-core systems, cheap memory (buy lots) even cheaper storage (buy lots lots) and unlimited bandwidth that question is often not even thought of until an application is going through the final performance tests.
And at that point your company's performance guy (been there, done that) might say - bad - things like :
- Those response times are - imo - not acceptable for production, what did you expect ?
- That is a very high throughput you've got there, what did you expect ?
- The cpus on the system are going red-hot, what did you expect ?
With a deadline looming like the sword of Damocles above your head, these are not things you want to hear.
The question "What do you expect ?" should be asked a lot earlier, it should be asked in the design phase, before any coding is done. The cost of overhauling a design is a lot lower than the cost of overhauling a completely finished application.
Now, next to the fact that NetKernel has an extremely light footprint on your systems as well as superior caching, it also has the tools to help you stay within the limits of what you expect.
The second graph is from a virtual machine (CentOS, single core), running on the same laptop !
So why is the blue line flat on the first graph ? I don't know, but I better find out before I make any conclusions about applications running on that system. And that is the point of my story. You must know what you expect, what the constraints on your application are before you write it. And NetKernel can help you with that.
Footnote :
On seeing the above issue, the 1060 Research crew jumped in and pointed out the obvious cause of the flatliner. I've got a pretty speedy laptop. And to optimize caching, NetKernel has a cost threshold parameter described as : cost of an item must be at least this high before eligible for caching. Can you see where this is going ? The native machine (but not the vm) responded so fast that nothing was costly enough to be cached. Hence the flatliner.
Easily ammended, I set the cost threshold to 0. And look :
I want to focus on that question today. For in these days of multi-core systems, cheap memory (buy lots) even cheaper storage (buy lots lots) and unlimited bandwidth that question is often not even thought of until an application is going through the final performance tests.
And at that point your company's performance guy (been there, done that) might say - bad - things like :
- Those response times are - imo - not acceptable for production, what did you expect ?
- That is a very high throughput you've got there, what did you expect ?
- The cpus on the system are going red-hot, what did you expect ?
With a deadline looming like the sword of Damocles above your head, these are not things you want to hear.
The question "What do you expect ?" should be asked a lot earlier, it should be asked in the design phase, before any coding is done. The cost of overhauling a design is a lot lower than the cost of overhauling a completely finished application.
Now, next to the fact that NetKernel has an extremely light footprint on your systems as well as superior caching, it also has the tools to help you stay within the limits of what you expect.
Take nkperf. You can install this tool from the repository and it tells you how your system behaves. Not relevant you say ? Read this newsletter entry again. Or if you'd rather not have a rehashed ;-) story, look at what I found this morning on my own laptop (Windows, dual core intel) :
Oops, there is something very fishy with my caching performance. Especially when you look at this :
The second graph is from a virtual machine (CentOS, single core), running on the same laptop !
So why is the blue line flat on the first graph ? I don't know, but I better find out before I make any conclusions about applications running on that system. And that is the point of my story. You must know what you expect, what the constraints on your application are before you write it. And NetKernel can help you with that.
Footnote :
On seeing the above issue, the 1060 Research crew jumped in and pointed out the obvious cause of the flatliner. I've got a pretty speedy laptop. And to optimize caching, NetKernel has a cost threshold parameter described as : cost of an item must be at least this high before eligible for caching. Can you see where this is going ? The native machine (but not the vm) responded so fast that nothing was costly enough to be cached. Hence the flatliner.
Easily ammended, I set the cost threshold to 0. And look :
2012/03/01
Five Step Tango
You know how you can often discover new things from re-reading (re-hearing) an old story ? I'm sitting in on a NetKernel training in the Twin Cities this week and while I have been in a similar training two or three times already, the following never took hold in my mind ...
Writing a physical endpoint contains five steps.
Now, such a statement is rather important given that there's nothing but spaces and endpoints (within those spaces) in NetKernel! So I don't know how I missed it in the previous sessions. Must be my selective hearing impediment.
Step 1. What is it you want ?
From the point of view of the physical endpoint that just got resolved to, this is rather important information. And it is available :
context.getThisRequest();
Step 2. What do I need to satisfy this request ?
Well, there are several possibilities here. Arguments passed to the request for example :
context.getThisRequest.getArgumentValue("...");
Also, subrequests may be needed :
context.createRequest(...);
Step 3. Add value
Be creative here!
Step 4. Prepare a response
Once the endpoint has done what it is supposed to do, it is time to create a response.
context.createResponseFrom(...);
Step 5. Set metadata on the response
This is an optional step (the five step tango also really has only four steps), most of the time the defaults will be fine. But you can :
response = context.createResponseFrom(...);
response.setMimeType("text/plain");
There, that is all there is to writing a physical endpoint. Enjoy!
Writing a physical endpoint contains five steps.
Now, such a statement is rather important given that there's nothing but spaces and endpoints (within those spaces) in NetKernel! So I don't know how I missed it in the previous sessions. Must be my selective hearing impediment.
Step 1. What is it you want ?
From the point of view of the physical endpoint that just got resolved to, this is rather important information. And it is available :
context.getThisRequest();
Step 2. What do I need to satisfy this request ?
Well, there are several possibilities here. Arguments passed to the request for example :
context.getThisRequest.getArgumentValue("...");
Also, subrequests may be needed :
context.createRequest(...);
Step 3. Add value
Be creative here!
Step 4. Prepare a response
Once the endpoint has done what it is supposed to do, it is time to create a response.
context.createResponseFrom(...);
Step 5. Set metadata on the response
This is an optional step (the five step tango also really has only four steps), most of the time the defaults will be fine. But you can :
response = context.createResponseFrom(...);
response.setMimeType("text/plain");
There, that is all there is to writing a physical endpoint. Enjoy!
2012/02/24
Wayback Machine
Have you ever taken a look at the Wayback Machine? In these days of the fast and the furious internet too few of us take time to look back at how things were in the not so distant past.
It may therefore be of interest to you to know that the more serious of the reverse engineers (I refuse to call them hackers, but that is a story for another day) do know about the Wayback Machine.
The way it works is that it constantly crawls the web and keeps a copy (by datestamp) of pages that have changed since the last crawl.
In ROC terms (you knew this was coming, right ?) the Wayback Machine holds on to expired (= no longer valid) representations of a resource. When I say no longer valid, I mean no longer valid now, for within the correct context - a given date - they are of course valid. There, the explanation of a time machine by a none-scientist!
NetKernel has it's very own time machine. It is called the Visualizer. It holds on to representations of resources. How ? By tagging them in the cache. For all other purposes these representations may be expired, but as long has the Visualizer has them tagged, they are not removed from the cache and can be consulted.
To see it at work, start it, then consult a couple of pages in the Backend Fulcrum. Go back to the Visualizer, stop it and take a look (in detail) at what you just did. It is that simple.
There is no debugging tool on the market that can stand even close to it. Let me repeat that. There is no debugging tool on the market that can stand even close to it. Most of them are postmortem tools, you have to reconstruct what happened. The (more expensive) ones that allow real time debugging suffer from the quantum problem : "Once you stick in your instruments to measure, you've changed the thing you want to measure".
The Visualizer suffers from neither problem. It is a true time machine. Go check it out. Today!
For those of you that are not convinced ... the Wayback Machine and its counterparts get more hits from reverse engineers (and I'm not talking script kiddies here) then by any other group of users. These are people that know how to use things like SoftIce (now Syser), Java Decompilers, javascript injection, ... Why would they bother with a rather boring website ? Out of historic interest ? I think not ...
It may therefore be of interest to you to know that the more serious of the reverse engineers (I refuse to call them hackers, but that is a story for another day) do know about the Wayback Machine.
The way it works is that it constantly crawls the web and keeps a copy (by datestamp) of pages that have changed since the last crawl.
In ROC terms (you knew this was coming, right ?) the Wayback Machine holds on to expired (= no longer valid) representations of a resource. When I say no longer valid, I mean no longer valid now, for within the correct context - a given date - they are of course valid. There, the explanation of a time machine by a none-scientist!
NetKernel has it's very own time machine. It is called the Visualizer. It holds on to representations of resources. How ? By tagging them in the cache. For all other purposes these representations may be expired, but as long has the Visualizer has them tagged, they are not removed from the cache and can be consulted.
To see it at work, start it, then consult a couple of pages in the Backend Fulcrum. Go back to the Visualizer, stop it and take a look (in detail) at what you just did. It is that simple.
There is no debugging tool on the market that can stand even close to it. Let me repeat that. There is no debugging tool on the market that can stand even close to it. Most of them are postmortem tools, you have to reconstruct what happened. The (more expensive) ones that allow real time debugging suffer from the quantum problem : "Once you stick in your instruments to measure, you've changed the thing you want to measure".
The Visualizer suffers from neither problem. It is a true time machine. Go check it out. Today!
For those of you that are not convinced ... the Wayback Machine and its counterparts get more hits from reverse engineers (and I'm not talking script kiddies here) then by any other group of users. These are people that know how to use things like SoftIce (now Syser), Java Decompilers, javascript injection, ... Why would they bother with a rather boring website ? Out of historic interest ? I think not ...
2012/02/17
Time of the Tree
Before I discovered NetKernel, my physical library consisted of a copy (= immutable representation) of the LOTR books as well as everything Stephen King had written up to that point (I actually learned English from reading "The Tommyknockers" over and over again, so blame him if my English is far from perfect).
Since then countless books on mathematics have been added as well as a (treasured) copy of The Codebreakers (the 1967 edition), books on evolutionary biology, ... the list goes on and on ...
So I was rather pleased last week after reading the NetKernel newsletter that I could go back to the roots and read up on the Ents. For after all, trees need guardians don't they ?
Do I agree with what Peter says in the article ? Well, as a database administrator I've seen the demise of the hierarchical (tree) database, the coming and going of the network oriented (codasyl) database and the rise of the relational (codd) database. And just now the latter is under fire by the nosql/document database. And the funny thing is that a document is a tree, instead of there being something new we've actually come full circle.
So yes, he might have a point. And the Hierachical Data Structure brings this datastructure neatly to your code, because lets be frank, it is a pain if the datastructure in your code differs from the one on the database. Let us - for example - take a look at the active:fls accessor. It takes an IHDSNode as input :
<root>
<fls>
<root>file:/var/tmp</root>
<recursive/>
<filter>*.tmp</filter>
</fls>
</root>
Yes, I do know that is XML. It is just a representation, a way of viewing at HDS. Every IHDSNode has a root element which may be ignored for practical purposes. Incoming XML (for example) is transrepted into a tree underneath this element. On the way out the element is removed.
This will make it more clear :
root : null
fls : null
root : file:/var/tmp
recursive : null
filter : *.tmp
fls : null
root : file:/tmp
filter : *.bak
The above IHDSNode contains a forest, not just a single tree. Normally speaking you can not transrept this to an XML representation (an XML can not contain a forest). But the transreptor has foreseen this (border) case and turns it into :
<hds>
<fls>
<root>file:/var/tmp</root>
<recursive/>
<filter>*.tmp</filter>
</fls>
<fls>
<root>file:/tmp</root>
<recursive/>
<filter>*.bak</filter>
</fls>
</hds>
Whereas the original example transrepts to :
<fls>
<root>file:/var/tmp</root>
<recursive/>
<filter>*.tmp</filter>
</fls>
Since one has to be careful these days ... for the purpose of this blog entry I define a forest as a group of two or more trees.
Did you notice the similarity with JSON ? Here is another possible representation :
{ "fls" : null {
"root" : "file:/var/tmp",
"recursive": null,
"filter": "*.tmp"
},
"fls" : null {
"root" : "file:/tmp",
"filter" : "*.bak"
}
}
Do you see my point ? I could not care less when I read that XML is dead and that JSON Rules. For I guarantee it, before the year is out, somebody with clout will get tired of typing curly brackets and invent something new (and if nobody does, I will). Bullshit (forgive me my French) ! Debating representations is moot. We care about resources. And the Time of the Tree has arrived (once more) ! Check it (HDS) out !
For your information, here's the Groovy program I did my experiments with :
import org.netkernel.layer0.nkf.INKFResponse;
import org.netkernel.layer0.representation.IHDSNode;
import org.netkernel.layer0.representation.impl.HDSBuilder;
builder = new HDSBuilder()
builder.pushNode("fls",null);
builder.addNode("root","file:/var/tmp");
builder.addNode("recursive",null);
builder.addNode("filter","*.tmp");
builder.popNode();
builder.pushNode("fls",null);
builder.addNode("root","file:/tmp");
builder.addNode("filter","*.bak");
builder.popNode();
response = context.createResponseFrom(builder.getRoot());
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
That's it for this week ... O yes, for obvious reasons, Tom Bombadil is my favorite character in LOTR, but Treebeard does come in a close second.
Since then countless books on mathematics have been added as well as a (treasured) copy of The Codebreakers (the 1967 edition), books on evolutionary biology, ... the list goes on and on ...
So I was rather pleased last week after reading the NetKernel newsletter that I could go back to the roots and read up on the Ents. For after all, trees need guardians don't they ?
Do I agree with what Peter says in the article ? Well, as a database administrator I've seen the demise of the hierarchical (tree) database, the coming and going of the network oriented (codasyl) database and the rise of the relational (codd) database. And just now the latter is under fire by the nosql/document database. And the funny thing is that a document is a tree, instead of there being something new we've actually come full circle.
So yes, he might have a point. And the Hierachical Data Structure brings this datastructure neatly to your code, because lets be frank, it is a pain if the datastructure in your code differs from the one on the database. Let us - for example - take a look at the active:fls accessor. It takes an IHDSNode as input :
<root>
<fls>
<root>file:/var/tmp</root>
<recursive/>
<filter>*.tmp</filter>
</fls>
</root>
Yes, I do know that is XML. It is just a representation, a way of viewing at HDS. Every IHDSNode has a root element which may be ignored for practical purposes. Incoming XML (for example) is transrepted into a tree underneath this element. On the way out the element is removed.
This will make it more clear :
root : null
fls : null
root : file:/var/tmp
recursive : null
filter : *.tmp
fls : null
root : file:/tmp
filter : *.bak
The above IHDSNode contains a forest, not just a single tree. Normally speaking you can not transrept this to an XML representation (an XML can not contain a forest). But the transreptor has foreseen this (border) case and turns it into :
<hds>
<fls>
<root>file:/var/tmp</root>
<recursive/>
<filter>*.tmp</filter>
</fls>
<fls>
<root>file:/tmp</root>
<recursive/>
<filter>*.bak</filter>
</fls>
</hds>
Whereas the original example transrepts to :
<fls>
<root>file:/var/tmp</root>
<recursive/>
<filter>*.tmp</filter>
</fls>
Since one has to be careful these days ... for the purpose of this blog entry I define a forest as a group of two or more trees.
Did you notice the similarity with JSON ? Here is another possible representation :
{ "fls" : null {
"root" : "file:/var/tmp",
"recursive": null,
"filter": "*.tmp"
},
"fls" : null {
"root" : "file:/tmp",
"filter" : "*.bak"
}
}
Do you see my point ? I could not care less when I read that XML is dead and that JSON Rules. For I guarantee it, before the year is out, somebody with clout will get tired of typing curly brackets and invent something new (and if nobody does, I will). Bullshit (forgive me my French) ! Debating representations is moot. We care about resources. And the Time of the Tree has arrived (once more) ! Check it (HDS) out !
For your information, here's the Groovy program I did my experiments with :
import org.netkernel.layer0.nkf.INKFResponse;
import org.netkernel.layer0.representation.IHDSNode;
import org.netkernel.layer0.representation.impl.HDSBuilder;
builder = new HDSBuilder()
builder.pushNode("fls",null);
builder.addNode("root","file:/var/tmp");
builder.addNode("recursive",null);
builder.addNode("filter","*.tmp");
builder.popNode();
builder.pushNode("fls",null);
builder.addNode("root","file:/tmp");
builder.addNode("filter","*.bak");
builder.popNode();
response = context.createResponseFrom(builder.getRoot());
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
That's it for this week ... O yes, for obvious reasons, Tom Bombadil is my favorite character in LOTR, but Treebeard does come in a close second.
2012/02/09
TRL
I've had some feedback that I worry too much about even-toed ungulates, so this week I'll play it safe and give a short example of the newest TRL - Text Recursion Language feature.
Now, TRL is itself a recent addition to the NetKernel toolkit and the little sister of XRL - XML Recursion Language. In retrospect it was a missing child, for with Freemarker + TRL for text and XSLT + XRL for xml those two formats (which will both be around for a long time to come) are now pretty well covered.
No idea what a future (?) JSLT and JRL (with the J for JSON) will look like, but the format has great momentum and at some point the need for both tools will arise.
Little sisters often take the lead (mine provided my schoolbooks with neat covers long before I could cut straight with scissors ... and she reminds me of that until this very day) and TRL is no exception. Last week asynchronity was added to it. XRL will no doubt follow soon.
What does that mean ? Well, take this simple example :
<sequence>
<request assignment="response">
<identifier>active:trl</identifier>
<argument name="template">
<literal type="string">
<![CDATA[
Hello ${
<request>
<identifier>active:groovy</identifier>
<argument name="operator">
<literal type="string">
import org.netkernel.layer0.nkf.INKFResponse;
sleep(1000);
response = context.createResponseFrom("Tom");
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
</literal>
</argument>
</request>
} ${
<request>
<identifier>active:groovy</identifier>
<argument name="operator">
<literal type="string">
import org.netkernel.layer0.nkf.INKFResponse;
sleep(1000);
response = context.createResponseFrom("Geudens");
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
</literal>
</argument>
</request>
}
]]>
</literal>
</argument>
</request>
</sequence>
You can execute this in the Scripting Playpen (as DPML obviously). By the way, the <![CDATA[ ]]> is needed in order to put XML inside a string literal without having to escape it (thanks to Peter Rodgers for pointing that out).
The example itself doesn't do a lot, but time it with the Visualizer. You'll get something like 2010 ms. Which is to be expected with the two sleeps that are executed synchronously.
Now, try this :
Time it again. You should get something like 1010 ms. We just halved execution time! The tradeoff - always be aware of those - is an extra thread. Still impressive. Go play with it! Try some recursion (a recursive example would have made the above completely unreadable).
To finish this entry ... it has been suggested that if we - humans - would have had an even number of digits on each hand/foot, we might have invented binary (and thus started the digital age) a lot sooner.
Now, TRL is itself a recent addition to the NetKernel toolkit and the little sister of XRL - XML Recursion Language. In retrospect it was a missing child, for with Freemarker + TRL for text and XSLT + XRL for xml those two formats (which will both be around for a long time to come) are now pretty well covered.
No idea what a future (?) JSLT and JRL (with the J for JSON) will look like, but the format has great momentum and at some point the need for both tools will arise.
Little sisters often take the lead (mine provided my schoolbooks with neat covers long before I could cut straight with scissors ... and she reminds me of that until this very day) and TRL is no exception. Last week asynchronity was added to it. XRL will no doubt follow soon.
What does that mean ? Well, take this simple example :
<sequence>
<request assignment="response">
<identifier>active:trl</identifier>
<argument name="template">
<literal type="string">
<![CDATA[
Hello ${
<request>
<identifier>active:groovy</identifier>
<argument name="operator">
<literal type="string">
import org.netkernel.layer0.nkf.INKFResponse;
sleep(1000);
response = context.createResponseFrom("Tom");
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
</literal>
</argument>
</request>
} ${
<request>
<identifier>active:groovy</identifier>
<argument name="operator">
<literal type="string">
import org.netkernel.layer0.nkf.INKFResponse;
sleep(1000);
response = context.createResponseFrom("Geudens");
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
</literal>
</argument>
</request>
}
]]>
</literal>
</argument>
</request>
</sequence>
You can execute this in the Scripting Playpen (as DPML obviously). By the way, the <![CDATA[ ]]> is needed in order to put XML inside a string literal without having to escape it (thanks to Peter Rodgers for pointing that out).
The example itself doesn't do a lot, but time it with the Visualizer. You'll get something like 2010 ms. Which is to be expected with the two sleeps that are executed synchronously.
Now, try this :
<sequence>
<request assignment="response">
<identifier>active:trl</identifier>
<argument name="template">
<literal type="string">
<![CDATA[
Hello $a{
<request>
<identifier>active:groovy</identifier>
<argument name="operator">
<literal type="string">
import org.netkernel.layer0.nkf.INKFResponse;
sleep(1000);
response = context.createResponseFrom("Tom");
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
</literal>
</argument>
</request>
} $a{
<request>
<identifier>active:groovy</identifier>
<argument name="operator">
<literal type="string">
import org.netkernel.layer0.nkf.INKFResponse;
sleep(1000);
response = context.createResponseFrom("Geudens");
response.setExpiry(INKFResponse.EXPIRY_ALWAYS);
</literal>
</argument>
</request>
}
]]>
</literal>
</argument>
</request>
</sequence>
Time it again. You should get something like 1010 ms. We just halved execution time! The tradeoff - always be aware of those - is an extra thread. Still impressive. Go play with it! Try some recursion (a recursive example would have made the above completely unreadable).
To finish this entry ... it has been suggested that if we - humans - would have had an even number of digits on each hand/foot, we might have invented binary (and thus started the digital age) a lot sooner.
Subscribe to:
Posts (Atom)

