Running EYE on swipl-wasm

We were able to run EYE on swipl.wasm :sunglasses:

What we did for Ubuntu is available at josd.github.io/temp/eye-wasm at master · josd/josd.github.io · GitHub

sudo apt install cmake
sudo apt install ninja-build

cd ~
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

cd ~
wget https://zlib.net/zlib-1.2.11.tar.gz -O "$HOME/zlib-1.2.11.tar.gz"
tar -xf "$HOME/zlib-1.2.11.tar.gz" -C "$HOME"
cd "$HOME/zlib-1.2.11"
emconfigure ./configure
emmake make

cd ~/github.com/SWI-Prolog/swipl-devel
mkdir build.wasm
cd build.wasm
source ~/emsdk/emsdk_env.sh
export EMSCRIPTEN=~/emsdk/upstream/emscripten/
ALLOW_MEMORY_GROWTH=1")
cmake -DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Modules/Platform/Emscripten.cmake \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -s ASSERTIONS=1 -s ALLOW_MEMORY_GROWTH=1" \
  -DZLIB_LIBRARY=$HOME/zlib-1.2.11/libz.a \
  -DZLIB_INCLUDE_DIR=$HOME/zlib-1.2.11 \
  -DMULTI_THREADED=OFF \
  -DUSE_SIGNALS=OFF \
  -DUSE_GMP=OFF \
  -DBUILD_SWIPL_LD=OFF \
  -DSWIPL_PACKAGES=OFF \
  -DINSTALL_DOCUMENTATION=OFF \
  -DSWIPL_NATIVE_FRIEND=build \
  -G Ninja ..
ninja

cd ~/github.com/josd/josd.github.io/temp/eye-wasm
node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope socrates.n3 --query socrates-query.n3
node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope gps-plugin.n3 gps-example1.n3 --query gps-query1.n3
node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope test-dt.n3 test-facts.n3 --query test-query.n3

The first test which is about socrates runs fine

$ node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope socrates.n3 --query socrates-query.n3
eye --nope socrates.n3 --query socrates-query.n3
EYE v22.0203.1955 josd
SWI-Prolog version 8.5.7-26-g4a0a2091e-DIRTY
starting 0 [msec cputime] 434 [msec walltime]
#Processed by EYE v22.0203.1955 josd
#eye --nope socrates.n3 --query socrates-query.n3

GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/socrates.n3 SC=3
GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/socrates-query.n3 SC=1
networking 0 [msec cputime] 49 [msec walltime]
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <http://example.org/socrates#>

:Socrates a :Human.
:Socrates a :Mortal.

reasoning 0 [msec cputime] 2 [msec walltime]
#2022-02-18T13:04:30.742Z in=4 out=2 ent=3 step=6 brake=2 inf=624805 sec=0.000 inf/sec=
#ENDS

2022-02-18T13:04:30.742Z in=4 out=2 ent=3 step=6 brake=2 inf=624805 sec=0.000 inf/sec=

The second test which is about GPS4IntegratedCare also runs fine

$ node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope gps-plugin.n3 gps-example1.n3 --query gps-query1.n3
eye --nope gps-plugin.n3 gps-example1.n3 --query gps-query1.n3
EYE v22.0203.1955 josd
SWI-Prolog version 8.5.7-26-g4a0a2091e-DIRTY
starting 0 [msec cputime] 426 [msec walltime]
#Processed by EYE v22.0203.1955 josd
#eye --nope gps-plugin.n3 gps-example1.n3 --query gps-query1.n3

GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/gps-plugin.n3 SC=7
GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/gps-example1.n3 SC=5
GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/gps-query1.n3 SC=1
networking 0 [msec cputime] 70 [msec walltime]
PREFIX math: <http://www.w3.org/2000/10/swap/math#>
PREFIX list: <http://www.w3.org/2000/10/swap/list#>
PREFIX log: <http://www.w3.org/2000/10/swap/log#>
PREFIX e: <http://eulersharp.sourceforge.net/2003/03swap/log-rules#>
PREFIX gps: <http://josd.github.io/eye/reasoning/gps/gps-schema#>
PREFIX : <http://josd.github.io/eye/reasoning#>

:i1 gps:path ((:drive_gent_brugge :drive_brugge_oostende) 2400.0 0.01 0.9408 0.99).
:i1 gps:path ((:drive_gent_kortrijk :drive_kortrijk_brugge :drive_brugge_oostende) 4100.0 0.018000000000000002 0.903168 0.9801).

reasoning 0 [msec cputime] 10 [msec walltime]
#2022-02-18T13:04:48.052Z in=13 out=2 ent=2 step=2 brake=2 inf=685808 sec=0.000 inf/sec=
#ENDS

2022-02-18T13:04:48.052Z in=13 out=2 ent=2 step=2 brake=2 inf=685808 sec=0.000 inf/sec=

The last test which is the 100000 deep taxonomy benchmark runs out of memory

$ node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope test-dt.n3 test-facts.n3 --query test-query.n3
eye --nope test-dt.n3 test-facts.n3 --query test-query.n3
EYE v22.0203.1955 josd
SWI-Prolog version 8.5.7-26-g4a0a2091e-DIRTY
starting 0 [msec cputime] 420 [msec walltime]
#Processed by EYE v22.0203.1955 josd
#eye --nope test-dt.n3 test-facts.n3 --query test-query.n3

GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/test-dt.n3 [FATAL ERROR: at Fri Feb 18 11:42:28 2022
        Cannot report error: no memory]
Aborted(native code called abort())
exiting due to exception: RuntimeError: Aborted(native code called abort()),RuntimeError: Aborted(native code called abort())
    at abort (/home/jdroo/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js:1:21763)
    at _abort (/home/jdroo/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js:1:101328)
    at <anonymous>:wasm-function[1497]:0xc7d51
    at <anonymous>:wasm-function[988]:0x9c2f9
    at <anonymous>:wasm-function[472]:0x30a56
    at <anonymous>:wasm-function[70]:0x3e4d
    at <anonymous>:wasm-function[1602]:0xcd05f
    at <anonymous>:wasm-function[1601]:0xccfc7
    at invoke_iiii (/home/jdroo/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js:1:122082)
    at <anonymous>:wasm-function[732]:0x5c2e3

but when running the same benchmark with webeye it works fine

$ /usr/bin/time -f "sec=%e0 kB=%M cpu=%P" node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -g run,halt webeye.pl dt.pl
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'('http://example.org/ns#z','http://example.org/ns#N100000') => true.
sec=29.830 kB=504168 cpu=108%

When compared with the native swipl

$ /usr/bin/time -f "sec=%e0 kB=%M cpu=%P" swipl -g run,halt webeye.pl dt.pl
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'('http://example.org/ns#z','http://example.org/ns#N100000') => true.
sec=8.380 kB=190200 cpu=114%

we see that swipl.js is about 3.5 times slower and uses about 2.5 times more memory, but that really looks nice when compared with https://twitter.com/josderoo/status/1494097945767161862 :slightly_smiling_face:

3 Likes

It is indeed 32 bit and all I did was a fresh Building SWI-Prolog using cmake - WASM (Emscripten) with some minor change documented here.
It is indeed without bignum support (and also without sha, pcre, … but wait and see what @dgelessus can do) but it is a nice beginning of an exciting journey and at least the following works fine

$ node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js
Welcome to SWI-Prolog (32 bits, version 8.5.7-27-g1c0c6729c)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

    CMake built from "/home/jdroo/github.com/SWI-Prolog/swipl-devel/build.wasm"

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

1 ?- X is 1.0*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20*21*22*23*24*25*26*27*28.
X = 3.0488834461171384e+29.X = 3.0488834461171384e+29.

2 ?-

The out of memory for the 100000 deep taxonomy benchmark can be avoided by splitting it in 2 times 50000 deep taxonomies

$ node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -f eye.pl -g main -- --nope test-dt1.n3 test-dt2.n3 test-facts.n3 --query test-query.n3
eye --nope test-dt1.n3 test-dt2.n3 test-facts.n3 --query test-query.n3
EYE v22.0203.1955 josd
SWI-Prolog version 8.5.7-27-g1c0c6729c
starting 0 [msec cputime] 441 [msec walltime]
#Processed by EYE v22.0203.1955 josd
#eye --nope test-dt1.n3 test-dt2.n3 test-facts.n3 --query test-query.n3

GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/test-dt1.n3 SC=50000
GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/test-dt2.n3 SC=50001
GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/test-facts.n3 SC=2
GET file:///home/jdroo/github.com/josd/josd.github.io/temp/eye-wasm/test-query.n3 SC=1
networking 0 [msec cputime] 42937 [msec walltime]
PREFIX : <http://eulersharp.sourceforge.net/2009/12dtb/test#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

:TestVariable a :A2.

reasoning 0 [msec cputime] 15490 [msec walltime]
#2022-02-19T01:00:11.338Z in=100004 out=1 ent=299999 step=200002 brake=2 inf=141206291 sec=0.000 inf/sec=
#ENDS

2022-02-19T01:00:11.338Z in=100004 out=1 ent=299999 step=200002 brake=2 inf=141206291 sec=0.000 inf/sec=

superdense coding using discrete quantum computing now also works fine

$ node ~/github.com/SWI-Prolog/swipl-devel/build.wasm/src/swipl.js -g run,halt webeye.pl sdcoding.pl
'https://idlabresearch.github.io/ns#sdcoding'(1,1) => true.
'https://idlabresearch.github.io/ns#sdcoding'(3,3) => true.
'https://idlabresearch.github.io/ns#sdcoding'(0,0) => true.
'https://idlabresearch.github.io/ns#sdcoding'(2,2) => true.

Yes indeed, but the whole point is that once the bootstrap is there it will all just run in the browser!

Right, now it is not yet there but stay tuned and with the help of https://twitter.com/timberners_lee and https://twitter.com/RubenVerborgh we’ll get the full potential of https://solidproject.org/ and things will definitely work out :sunglasses:

1 Like

OT: why the deletion of your message(s) ? I feel deprived of half of this interesting topic…

It runs on node but it should be on any OS and not just Linux.
It is now available at eyenext and includes the pre-build swipl-wasm.

It is using the Web language N3 invented by the web inventor Tim Berners-Lee. It has no negation and no disjunction so is not first order logic, be it that some built-ins go beyond first order logic.

For a language like Prolog, 64-bit tagged words and pointers is a good thing. I’d love to see 64-bit wasm soon… It was in the roadmap but AFAIK no browser supports it.

1 Like

How about the 100000 deep taxonomy benchmark

swipl.js -g run,halt webeye.pl dt.pl

versus Doge?

The 2 files are at webeye.pl and dt.pl and for some background see deep taxonomy benchmark.

This benchmark was designed by the late Harold Boley and is interesting to evaluate the subsumption capabilities of reasoners (using RDF and OWL)
e.g.
[[
SNOMED CT currently contains more than 300,000 medical concepts, divided into
hierarchies as diverse as body structure, clinical findings, geographic location and
pharmaceutical/biological product
]] – What is SNOMED CT (Systematized Nomenclature of Medicine -- Clinical Terms) ? - Definition from WhatIs.com

Will later report the runtime, when calling run .

Will stay tuned :+1:

We are mostly interested in the reasoning time i.e. time(run) in

$ node swipl-wasm/home/swipl.js -g "[webeye],time([dt]),time(run),halt"
% 44,101,092 inferences, 0.000 CPU in 26.988 seconds (0% CPU, Infinite Lips)
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'('http://example.org/ns#z','http://example.org/ns#N100000') => true.
% 9,300,046 inferences, 0.000 CPU in 5.325 seconds (0% CPU, Infinite Lips)

versus native swipl

$ swipl -g "[webeye],time([dt]),time(run),halt"
% 44,101,128 inferences, 4.233 CPU in 4.233 seconds (100% CPU, 10418275 Lips)
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'('http://example.org/ns#z','http://example.org/ns#N100000') => true.
% 9,300,046 inferences, 2.309 CPU in 2.310 seconds (100% CPU, 4027766 Lips)

so for time(run) swipl.js is about 2.3 times slower (and not the above 3.5 times @jan).

What about the many write/1 statements in webeye? Also I saw
on GitHub large log files in connection with running eye. Is this
a requirement for time(run) to measure the writing of log files?

Webeye is experimental and will probably never fly - we need N3 and this is what we now do in eyenext.
We have quite a strong requirement to produce proofs and that is not for log file purposes, so yes, writing should be included in the timing.

It is not needed for swipl but we added it to be able to run webeye with scryer-prolog as it contains numbervars/3. I am perplexed by the difference between https://github.com/mthom/scryer-prolog/blob/9ded1447ece6547f775b61d860579bef68af1260/src/lib/terms.pl and https://github.com/SWI-Prolog/swipl-devel/blob/4c2748bf518b4f07b0f973c73f80e69b23519a6a/library/terms.pl

But this was a log file of some generated rules during proof search?

https://raw.githubusercontent.com/josd/eye/master/reasoning/dt/test-dt.n3

A final proof might not use all of them? Or maybe it was the test case itself?

It is a file containing N3 rules and is part of the test case itself. It is generated via partial evaluation https://github.com/josd/eye/tree/master/reasoning/dt

Fair enough and it is exactly why I think that the late Harold Boley came up with this challenge.
It is fine and let us now further progress from Deep Taxonomy Benchmark which was made quite some years ago …

It’s nice to see that wasm version of SWI gets more usage! I hope to find more time to make the interface between Prolog and JS a bit more usable (and add TS typings). By the way, I think one way to improve both versions would be using read/2 or read_term/2 to load huge files like dt.pl as it would skip term/goal expansion compared to loading the data as Prolog source (I have seen difference of 10x). The wasm version contains (or at least used to) additional filesystem emulation layer at syscall level through musl libc on top of node filesystem layer and might be slower for io because of that too.

2 Likes

Thanks for all your excellent work, it is really good to see swipl running on Node.js like in eye-web and I was also trying to let hello world example running in the browser and using the latest swipl-web at https://github.com/josd/eye-web/tree/main/swipl-wasm/home .
I tried a few things also from your example but it didn’t work so far …
Would you mind having a look and eventually do a pull request?

At least the swipl-web files are loading fine:

~/github.com/josd/eye-web$ http-server
Starting up http-server, serving ./

http-server version: 14.1.0

http-server settings:
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none

Available on:
  http://127.0.0.1:8080
  http://172.28.61.45:8080
Hit CTRL-C to stop the server

[2022-02-21T16:54:42.666Z]  "GET /hello-world.html" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0"
(node:11660) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated
(Use `node --trace-deprecation ...` to show where the warning was created)
[2022-02-21T16:54:42.692Z]  "GET /swipl-wasm/home/swipl-web.js" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0"
[2022-02-21T16:54:42.724Z]  "GET /swipl-wasm/home/swipl-web.data" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0"
[2022-02-21T16:54:42.727Z]  "GET /swipl-wasm/home/swipl-web.wasm" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0"

There’s also fast binary term I/O. Unfortunately, it’s not (currently) portable to other Prologs.

Yes. If you know you just have to load terms, skipping all the admin makes things quite a bit faster. On a big wordnet file I see 0.485 vs. 1.75 sec.

1 Like