A few years ago I wanted to try to plug a serverless Prolog service to a Web app and I successfully managed to have SP running on a Google Cloud Run container (Cloud Run is a service firing container instances to serve requests, allowing one to use any language/environment they want; I used the minimal swipl Docker image provided officially for SP).
I’ve always been eager to find different solutions, though (easier to implement/less expensive etc).
Now, as I’ve seen that SP has WebAssembly support (I found the doc pages and the wiki page and discussion here), I wondered whether Firebase Functions could be used instead.
There are many advantages to using Firebase Functions, as a certain kind of them is callable directly from the client (they’re called “callable” for that) and has automatic support for authorization and a greatly simplified experience.
I tried the provided swipl-wasm package with a local Node project and I was able to use Prolog seamlessy with JS (and this is real “prog porn”, if you ask me).
(I couldn’t run it with the "swipl-wasm/dist/swipl"
entry point. It worked simply with "swipl-wasm"
.)
So I tried to deploy the same test as a Firebase Function.
(You define Firebase Functions by building them with the methods provided by the firebase-functions
API, by exporting them and by deploying them to the cloud.)
import functions from "firebase-functions";
import SWIPL from "swipl-wasm";
export const testBetween = functions.https.onCall(async (data, context) => {
const swipl = await SWIPL({ arguments: ["-q"] });
const result = [];
for (const res of swipl.prolog.query("between(1, 20, X)."))
result.push(res.X / 2);
return result;
});
The problem is that the swipl
allocation at the start of the function seems to trigger a memory build-up that surpasses the 256 MB limit imposed on Firebase Functions (and also the next one of 512 MB, I tried), so the function always fails.
I have three different questions:
-
What’s the reason for the memory issue and is it solvable?
-
In case it is solved and the function works, I’m not sure things are being properly cleaned up after getting the result; should I call
swipl.prolog.call("halt.")
or anything after issuing queries? -
Firebase Functions documentation suggests keeping expensive objects as global objects outside function definitions so that they may possibly be reused by function instances fired after a cold start (see here)
Would there be any issues with moving theswipl
object to the global scope and it being reused many times by different function calls? (I guess this also intersects the issue of multithreading)
Thanks.