The basic API stack uses for web access is simple:
- send a POST-request with
timeout
,ploturlbase
,version
andinput
- put the value of
ploturlbase
into a maxima variable - send
input
to the maxima process - if the maxima process is not finished after
timeout
milliseconds, return a 416 error - else return the output of
maxima
The web interface to the maxima processes is implemented in golang.
At startup, the server process starts the maxima mother process.
The server process maintains a queue of some maxima processes derived from the mother process and ready to use.
Each maxima process gets assigned a user of the form maxima-%d
which is a valid unix user (these are already there if you use the Docker image).
If a new request comes in, it takes a process from the queue and communicates with the process through some named pipes.
After it is finished (or the process timed out) all leftover process with the process' username are kill-9'd and temporary files/pipes deleted.
The user id is then again available for other processes.
At first, the server process creates a temporary directory for the future process and creates 2 pipes, inpipe and outpipe for stdin and stdout of maxima. The server then sends to the mother process the maxima user id and the path of the temporary directory.
The mother process is in a loop which is called at server startup:
(forking-loop)
is called, which was loaded through /assets/maxima-fork.lisp
which uses sbcl's FFI to call the forking loop fork_new_process()
in /src/maxima_fork.c
.
When it receives a new id and path, it forks a new maxima process from the mother process and does some setup.
Forking a process from an existing one is vastly more efficient (faster with a factor of around 10x) than execve'ing a new maxima process, and the memory consumption is reduced, too. It does have the caveat that, at run time, there will be more page faults because of the copy-on-write mechanics, which slows the process down.
After the child process responds that it is ready, the server process puts its description into a queue, where it is taken later for evaluating the request.