Ho una piccola ma pesante app per CPU in alpha stage in node.js, è un gioco di piccole dimensioni. Sto incontrando problemi di prestazioni e ho bisogno di accelerarlo di almeno un fattore di 20 per arrivare alla versione beta. E poiché l'esecuzione parallela mi avrebbe portato molto lontano, ho deciso che sarebbe stato un buon inizio condividere la mappa di gioco tra processi o thread che avrebbero eseguito operazioni parallele su di essa. Questo è piuttosto impossibile da fare nel nodo, così ho deciso di scrivere le parti carnose in CL (SBCL + Linux) e collegarmi ad esso tramite un unix dominio socket.Connetti Node.js come client a un server Common Lisp
Il piano è:
[players] <-> (node.js front server) <-> (SBCL performing game ticks)
Il punto è, ho bisogno di passare i messaggi veloci tra node.js e SBCL in una questione simile a socket.io.
Ecco cosa non ha funzionato (si può saltare questa parte)
Sul lato nodo, non posso utilizzare socket.io pianura perché non supporta Unix Domain Socket, ma il modulo net
sì, quindi posso almeno fare socket.write('raw data')
- meglio di niente per ora.
Sul lato CL, ho provato a eseguire woo web server (supporta socket locali) e potevo connettermi dal nodo e passare i dati grezzi in giro, ma ci sono tutte le parti HTTP non necessarie coinvolte e woo è sempre in esecuzione come server; sta aspettando il GET/HTTP/1.1 ....
. Non ho trovato il modo di avviare realmente un messaggio da woo prima. Inoltre, è totalmente non documentato e non commentato e coinvolge molte chiamate FF alle librerie C, che non conosco affatto.
Così ho passato molti altri server web CL che non sono stati compilati, non supporta socket unix, sono stati abbandonati o non documentati, eventualmente spostati in semplici sb-bsd-socket e infine in iolib, ma posso ancora ' lo capisco.
iolib sembrava promettente, ma non in grado di connettersi ad esso dal nodo.
ho questo:
(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))))
e sto ottenendo
#<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's top level.
4: [ABORT] abort thread (#<THREAD "worker" RUNNING {10055169A3}>)
Non so se devo chiamare qualcosa come accettare connessione o ascoltare-to su quel presa prima. Tutto ciò che ho provato ha causato errori. Inoltre, se I [RETRY-SYSCALL]
in repl, l'errore scompare per circa 10 secondi ma torna indietro. In questo momento, il nodo non riesce ancora a connettersi.
Questo sembra essere più complicato di quanto pensassi. Ho già perso ~ 6 ore di lavoro su iolib da solo e non ho nemmeno iniziare il parsing dei messaggi, imparare a creare gli eventi da loro, la conversione tra JSON e s-EXPS ecc ..
Le mie domande sono:
- come faccio a configurare questa connessione in modo iolib netta può collegarsi quel nodo?
- Supponendo che io possa scegliere, quale tipo di connessione sarebbe più adatta per trasmettere eventi/messaggi? (datagramma/stream)
- Ci sono alcuni strumenti di lavoro che non ho provato?
- Inoltre, ci sono altre librerie di iolib forse più di alto livello/meglio documentate?
- Esistono approcci migliori/più facili/più rapidi a questo problema di prestazioni/concorrenza?
- Altre idee?
Sono vicino a quasi abbandonando l'idea di CL e di usare qualcosa di simile in memoria mongo con diversi processi di nodo invece (..è in realtà non suona veloce), ma amo Lisp , sarebbe bello avere cose come lparallel sul backend. Non mi sono spostato di un pollice da ieri mattina, non riesco a capire le libs. Forse dovrei invece imparare il clojure.
PS: Normalmente non chiederei "scrivimi il codice", ma se c'è qualcosa di buono, lo apprezzerei molto, anche in pseudocodice.
PPS: sono benvenuti anche approcci radicalmente diversi. Per favore, parla chiaro :)
Grazie per la lettura!
Hai molte domande in queste domande, alcune relative a Lisp, altre più generali (scegli TCP vs UDP), quindi potrebbe essere un po 'troppo ampio. D'altra parte, la tua domanda è interessante. Non esitate a postare domande più mirate la prossima volta, se necessario. Esistono librerie per la comunicazione asincrona (cl-async), JSON (cl-json, yason) ecc. Che sono abbastanza stabili. Potrebbe essere meglio affrontare ogni problema separatamente, uno dopo l'altro. In bocca al lupo. – coredump