Queuing of Long Calculations
The standard usage of web
Mathematica 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, web
Mathematica 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.
web
Mathematica contains a simple example of the queuing system, the source for this can be found in the web
Mathematica 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.
<msp:evaluateQueued pool="Compute" var="id">
longCalculation[]
</msp:evaluateQueued>
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.
var | the name of a page variable to hold the job id |
pool | the pool to use for the compuation |
Attributes of the evaluateQueued 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. web
Mathematica offers an expression language function that helps to find the job.
<c:set var="job" value="${queue.jobs[param.id]}"/>
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.
errorType values | meaning |
NOERROR | job has no error |
KERNELEXCEPTION | a kernel exception occurred |
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 web
Mathematica, 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 web
Mathematica in the section on
configuration. Another advantage of a separate pool for queued calculations is that you have a pool available for normal calculations.