I have a small but heavy application with an alpha stage processor in node.js, this is a small game. I am facing performance issues and I need to speed it up at least 20 times to get to the beta. And since parallel execution would make me very far away, I decided that sharing a game map between processes or threads that would perform parallel operations on it would be a good start. This is pretty impossible to do in node, so I decided to write the meat parts in CL (SBCL + Linux) and connect to it through a unix domain socket.
Plan:
[players] <-> (node.js front server) <-> (SBCL performing game ticks)
The thing is, I need to pass fast messages between node.js and SBCL in a question like socket.io.
Here's what didn't work (you can skip this part)
On the Node side, I cannot use simple socket.io because it does not support Unix Domain Sockets, but the net module does, so I can at least make socket.write('raw data') - better than nothing at the moment,
On the CL side, I tried to start the woo web server (it supports local sockets), and I could connect to it from Node and send raw data, but there are all unnecessary parts of HTTP, and woo always works as a server; he is waiting for GET / HTTP/1.1 .... I did not find a way to initiate a message from woo in the first place. In addition, it is completely undocumented and commented out and includes many FF calls in C libs, which I am not familiar with at all.
So, I went through several more CL web servers that did not compile, did not support UNIX sockets, were left or undocumented, ended up moving to simple sb-bsd sockets and finally to iolib, but I still canβt find it out.
iolib looked promising, but I can't connect to it from node.
I have it:
(with-open-socket (socket :address-family :local :type :datagram ;; :connect :passive :local-filename "/tmp/socket") (format t "Socket created") ;; (listen-on socket) ;; (bind-address socket (make-address "/tmp/socket")) (loop (let ((msg (receive-from socket :size 20))) (format t msg))))
and i get
#<Syscall "recvfrom" signalled error EWOULDBLOCK(11) "Resource temporarily unavailable" FD=6> [Condition of type IOLIB/SYSCALLS:EWOULDBLOCK] Restarts: 0: [IGNORE-SYSCALL-ERROR] Ignore this socket condition 1: [RETRY-SYSCALL] Try to receive data again 2: [RETRY] Retry SLIME interactive evaluation request. 3: [*ABORT] Return to SLIME top level. 4: [ABORT] abort thread (
I don't know if I should first call something like accept-connection or listen-on on this socket. Everything I tried led to errors. Also, if I [RETRY-SYSCALL] in repl, the error disappears for about 10 seconds, but returns. During this time, Node is still unable to connect.
This seems more complicated than I thought. I already lost ~ 6 hours of work on iolib, and I did not even start parsing messages, learning how to create events from them, converting between JSON and s-exp, etc.
My questions are :
- How to establish this connection in iolib so that Node network can connect?
- Assuming I can choose which type of connection is best suited for transmitting events / messages? (datagram / stream)
- Are there any work tools that I have not tried?
- Also, are there some other libraries than iolib that are possibly higher level / better documented?
- Are there any more efficient / lighter / faster approaches to this performance / concurrency issue?
- Any other ideas?
I'm close to just dropping the CL idea and using something like in-memory mongo with multiple Node processes instead (... it really doesn't sound fast), but I like lisp, it would be great to have such things, like lparallel on the backend. I just haven't moved an inch since yesterday morning, I just can't understand the libraries. Perhaps I should learn clojure.
PS: Normally, I would not ask "write me a code", but if some good soul is around, I would really appreciate it, even in pseudo-code.
PPS: any radically different approaches are also welcome. Please give your opinion :)
Thank you for reading!