Queuing of Long Calculations
The standard usage of webMathematica carries out calculations inside of a single HTTP request. Mathematica can do a tremendous amount during an HTTP request and so many interesting websites can be built. However, if you want to run longer calculations, taking more time than a typical HTTP request, for example, a calculation that takes 20 minutes, this cannot be done with the standard usage.
When the evaluateQueued tag is processed, webMathematica creates a job object that waits in a queue until a kernel is available to do the calculation and the HTTP request returns immediately, probably before the computation has even started. At some time in the future, the request is run and any results are saved. The web client can make a request to the server, using an identifier for the job, at any time to find out what has happened to the request.
webMathematica contains a simple example of the queuing system, the source for this can be found in the webMathematica web application in the directory Examples/Queueing (the full path in Tomcat would be webapps/webMathematica/Examples/Queueing). There are three files, Start.jsp, which sets up parameters for the calculation, Submit.jsp, which actually submits the calculation to the queue, and Result.jsp, which waits for and displays the result.
The basis of the queueing system is the evaluateQueued tag, which is used instead of the evaluate tag. An example of the tag is shown below.
The body of the tag contains the long running calculation, in this case longCalculation[]. Note that if you load any package in this body, then you need to refer to the fully qualified name; this is discussed in more detail in the section Loading Packages. An alternative would be how to use the KernelInitializeCode configuration parameter to load any necessary packages.
The evaluateQueued tag actually creates a job object and places it into a queue. The job has an id that can be used to work with it later, and this can be found with the var attribute. When the job actually runs, it uses the pool set by the pool attribute; if this is not found, then it will use the standard URL mapping used by the evaluate tag.
The actual computation of the body of the evaluateQueued tag proceeds very similarly to the evaluate tag. The computation can make use of many of the MSP functions, for example, saving image files and constructing URLs. It also has access to all the request parameters that came with the request. However, it does not have access to an HTTP request object, and so it cannot make use of an HTTP session.
Interacting with the Queue
One key way that you can interact with the queue is using the var attribute of the evaluateQueued tag. This can be passed around the various web pages you want to work with, either as a request parameter or by saving in an HTTP session. An example, which starts a calculation, and then offers a link to another page passing the var as a request parameter, is shown below.
<msp:evaluateQueued pool="General" var="id">
longCalculation[]
</msp:evaluateQueued>
<p>Get results <a href="Result.jsp?id=${id}">here</a>.</p>
The var attribute is actually a variable that holds a reference to the id of the job object. webMathematica offers an expression language function that helps to find the job.
There are a number of things you can do with the job object. You can find out its state, whether it has started, finished, etc... You can find out its input and also the result, if it has finished. You can also cancel the job.
It is also possible to access the job object via the Mathematica syntax, when the kernel is initialized the symbol MSP`Utility`$Job is assigned to the job. Some functions for working with the job in both the expression language and Mathematica are shown below.
expression language syntax | Mathematica syntax | |
state of the job | ${job.state} | job@getState[] |
result of the computation | ${job.output} | job@getOutput[] |
id of the worker | ${job.id} | job@getId[] |
Some techniques for the job object.
The state property of the job object shows you what the state it is in. The possible values are shown below.
state values | meaning |
NEW | job has been created |
QUEUED | job is waiting in the queue |
RUNNING | job is running |
TERMINATED | job has terminated |
Values of the state property of the Job object.
The errorType and errorText properties of the job object show you information about the error state of the job. The possible values are shown below.
Values of the errorType property of the Job object.
If the state is TERMINATED, you can extract the result and you know that the job has finished the computation.
For example, the Result.jsp page has code that looks like the following.
<c:set var="queues" value="${applicationScope['com.wolfram.msp.JobQueueMap']}"/>
<c:set var="queue" value="${queues[param.name]}"/>
<c:set var="job" value="${queue.jobs[param.id]}"/>
<msp:constantsMap className="com.wolfram.kerneltools.state.State" var="State"/>
<c:choose>
<c:when test="${empty job}">
Job with Id ${param.id} not found.
</c:when>
<c:when test="${job.state == State.QUEUED}">
<p>The computation is queued until a kernel becomes available.</p>
<a href="Result.jsp?name=${param.name}&id=${param.id}">Check again?</a>
</c:when>
<c:when test="${job.state == State.RUNNING}">
<p>The computation is currently running.</p>
<a href="Result.jsp?name=${param.name}&id=${param.id}">Check again?</a>
</c:when>
<c:when test="${job.state == State.TERMINATED}">
Error text: ${job.errorText}<br/>
Error type: ${job.errorType}<br/>
<p>Here are some snapshots of the result.</p>
${job.output}
</c:when>
<c:otherwise>
Error with job ${job.id}
</c:otherwise>
</c:choose>
This shows how the job object is extracted from the request parameter, and how to get the state property. The page then returns different content depending on the value of the state.
Lifetime of a Queued Request
These are the steps in processing a queued request.
● A page that contains an evaluateQueued tag is processed. This creates a job object, chooses a kernel pool, and submits the job to the job queue for that pool. The pool is chosen from the pool attribute or a URL pattern if there is no pool attribute. If there is a var attribute it is bound to the id of the job. The state of the job is NEW when it is created and this moves to QUEUED once it is queued. Any request parameters that are sent with the page are saved to be used when the computation is actually run.
● The request that contains the evaluatedQueued tag returns to the client. This might contain a reference to the id of the job.
● At some future time a kernel in the pool becomes available. This kernel is acquired for the job. At this point any KernelAcquireCode configuration will be called. The job changes state from QUEUED to RUNNING.
● The kernel executes the body of the evaluateQueued tag. It is subject to all the constraints and limits of executing commands in webMathematica, and if one of these is exceeded then the computation will terminate and the errorType will be set to KERNELEXCEPTION. However, if the computation finished normally, the errorType is set to NOERROR and the result is stored in the job.
Organizing and Configuring a Queued Pool
Any kernel pool can be used to run computations from an evaluateQueued tag. However, it is typically good practice to have a pool that is designated for queued computations. More information about kernel pools and how to set them up can be found in the kernel pools section. Using a separate pool is advantageous because you can configure it in a way that is more useful for a queued computation. For example, you might want to increase the KernelTimeLimit parameter, to increase it to some longer value. Most of the configuration parameters are useful for a queued computation; you can find out more about configuring webMathematica in the section on configuration. Another advantage of a separate pool for queued calculations is that you have a pool available for normal calculations.